Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
A
admin-ci-test
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
test-ci
admin-ci-test
Commits
3018428e
提交
3018428e
authored
8月 01, 2023
作者:
龚洪江
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop'
上级
f4a13cc2
903a4367
隐藏空白字符变更
内嵌
并排
正在显示
43 个修改的文件
包含
3508 行增加
和
606 行删除
+3508
-606
kustomization.yaml
kustomization/overlays/dev/kustomization.yaml
+1
-1
categoryManage.ts
src/api/interface/categoryManage.ts
+59
-0
commonType.ts
src/api/interface/commonType.ts
+12
-0
goodsType.ts
src/api/interface/goodsType.ts
+164
-0
systemManageType.ts
src/api/interface/systemManageType.ts
+82
-0
categoryManage.ts
src/api/modules/categoryManage.ts
+32
-0
common.ts
src/api/modules/common.ts
+14
-0
goodsAPI.ts
src/api/modules/goodsAPI.ts
+29
-1
systemManage.ts
src/api/modules/systemManage.ts
+20
-0
request.ts
src/api/request.ts
+1
-1
qr-code-icon.svg
src/assets/image/qr-code-icon.svg
+2
-0
index.tsx
src/components/EditableCell/index.tsx
+20
-4
index.scss
src/components/layout/index.scss
+1
-0
index.tsx
src/components/layout/title/index.tsx
+2
-4
index.tsx
.../categoryList/components/addOrEditCategoryModal/index.tsx
+122
-0
index.scss
src/pages/categoryManage/categoryList/index.scss
+7
-0
index.tsx
src/pages/categoryManage/categoryList/index.tsx
+482
-0
index.scss
src/pages/common/login/index.scss
+20
-0
index.tsx
src/pages/common/login/index.tsx
+137
-53
index.tsx
src/pages/customManage/customList/index.tsx
+1
-1
index.scss
...ods/goodsAddOrEditOrDetail/components/baseInfo/index.scss
+10
-0
index.tsx
...oods/goodsAddOrEditOrDetail/components/baseInfo/index.tsx
+248
-0
index.tsx
...goodsAddOrEditOrDetail/components/introduceInfo/index.tsx
+21
-0
index.tsx
...sAddOrEditOrDetail/components/skuAddOrEditModal/index.tsx
+419
-0
index.tsx
...Goods/goodsAddOrEditOrDetail/components/skuInfo/index.tsx
+135
-0
index-old.tsx
...mallManage/mallGoods/goodsAddOrEditOrDetail/index-old.tsx
+308
-0
index.scss
...es/mallManage/mallGoods/goodsAddOrEditOrDetail/index.scss
+15
-10
index.tsx
...ges/mallManage/mallGoods/goodsAddOrEditOrDetail/index.tsx
+225
-264
index.scss
src/pages/mallManage/mallGoods/goodsDetails/index.scss
+25
-0
index.tsx
src/pages/mallManage/mallGoods/goodsDetails/index.tsx
+180
-0
index.tsx
src/pages/mallManage/mallGoods/goodsList/index.tsx
+116
-123
index.tsx
...yManage/companyDetail/components/addPeopleModal/index.tsx
+59
-0
index.tsx
...ge/companyDetail/components/transferLeaderModal/index.tsx
+75
-0
index.scss
...pages/systemManage/companyManage/companyDetail/index.scss
+21
-0
index.tsx
src/pages/systemManage/companyManage/companyDetail/index.tsx
+229
-0
index.tsx
...age/companyManage/companyList/comp/addEditModal/index.tsx
+90
-48
index.tsx
src/pages/systemManage/companyManage/companyList/index.tsx
+16
-9
index.ts
src/router/index.ts
+27
-31
privateRouter.tsx
src/router/privateRouter.tsx
+16
-10
router.tsx
src/router/router.tsx
+46
-19
index.ts
src/store/module/menu/index.ts
+6
-9
index.ts
src/store/module/userInfo/index.ts
+1
-18
validateUtils.ts
src/utils/validateUtils.ts
+12
-0
没有找到文件。
kustomization/overlays/dev/kustomization.yaml
浏览文件 @
3018428e
...
...
@@ -14,4 +14,4 @@ patches:
images
:
-
name
:
REGISTRY/NAMESPACE/IMAGE:TAG
newName
:
mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly-dev/admin
newTag
:
0
76c71a473e24a5f127df294af6ea3eb20b5858c
newTag
:
0
63cc3527bbd3e1199f9aec0d902b1c76c712a0a
src/api/interface/categoryManage.ts
浏览文件 @
3018428e
...
...
@@ -72,3 +72,62 @@ export type categoryDetailsType = InterFunction<
>
;
//分类-关联列表
export
type
categoryRelevantType
=
InterFunction
<
{
id
:
number
;
type
:
number
},
any
>
;
//分类管理-分类列表(新)
type
categoryItemType
=
{
id
:
number
;
name
:
string
;
createTime
:
string
;
icon
:
string
;
description
:
string
;
subDTOList
:
(
Omit
<
categoryItemType
,
'createTime'
|
'icon'
|
'subDTOList'
|
'sort'
>
&
{
categoryPrimaryId
:
number
;
})[];
sort
:
number
;
};
export
type
categoryListRespType
=
InterItemFunction
<
{
id
?:
number
},
categoryItemType
[]
>
;
//分类管理-1级分类新增(新)
export
type
addPrimaryCategoryType
=
InterFunction
<
{
description
:
string
;
icon
:
string
;
name
:
string
;
},
any
>
;
//分类管理-1级分类编辑(新)
export
type
updatePrimaryCategoryType
=
InterFunction
<
{
description
:
string
;
icon
:
string
;
name
:
string
;
id
?:
number
;
},
any
>
;
//分类管理-1级分类删除(新)
export
type
deletePrimaryCategoryType
=
InterFunction
<
{
id
:
number
},
any
>
;
//分类管理-1级分类交换顺序(新)
export
type
exchangeType
=
InterFunction
<
{
id
:
number
;
sort
:
number
}[],
any
>
;
//分类管理-2级分类新增(新)
export
type
addSubCategoryType
=
InterFunction
<
{
categoryPrimaryId
:
number
;
description
:
string
;
name
:
string
;
},
any
>
;
//分类管理-2级分类编辑(新)
export
type
updateSubCategoryType
=
InterFunction
<
{
categoryPrimaryId
:
number
;
description
:
string
;
name
:
string
;
id
?:
number
;
},
any
>
;
//分类管理-2级分类删除(新)
export
type
deleteSubCategoryType
=
InterFunction
<
{
id
:
number
},
any
>
;
src/api/interface/commonType.ts
浏览文件 @
3018428e
...
...
@@ -11,6 +11,7 @@ export type BackEndLoginType = InterFunction<
phoneNum
:
string
;
userName
:
string
;
nickName
:
string
;
appUserAccountId
?:
number
;
companyInfoVO
:
{
id
:
number
;
companyType
:
number
;
...
...
@@ -23,6 +24,7 @@ export type BackEndLoginType = InterFunction<
companyUserName
:
string
;
phoneNum
:
string
;
remark
:
string
;
leader
:
number
;
};
roleInfo
:
{
id
:
number
;
...
...
@@ -157,3 +159,13 @@ export type batchRemoveBannerInfo = InterFunction<any, NonNullable<unknown>>;
export
type
removeBannerInfo
=
InterFunction
<
{
id
:
number
},
NonNullable
<
unknown
>>
;
// V1.0.1-banner-排序交换
export
type
exchangeBannerInfo
=
InterFunction
<
Array
<
any
>
,
NonNullable
<
unknown
>>
;
//手机号筛选小程序用户
export
type
getUserAccountByPhoneNumType
=
InterFunction
<
{
phoneNum
:
string
},
{
id
:
number
;
nickName
:
string
;
userName
:
string
;
phoneNum
:
string
;
uid
:
string
}[]
>
;
//获取小程序二维码
export
type
appletQRCodeType
=
InterFunction
<
{
page
:
string
;
scene
:
string
},
string
>
;
//登录信息-获取
export
type
getLoginInfoType
=
InterFunction
<
{
randomLoginCode
:
string
},
any
>
;
src/api/interface/goodsType.ts
浏览文件 @
3018428e
...
...
@@ -99,7 +99,171 @@ export type otherServiceType = InterFunction<any, { id: number; saleServiceName:
export
type
skuUnitType
=
InterFunction
<
any
,
{
id
:
number
;
unitName
:
string
}[]
>
;
//商品-批量上下架
export
type
batchOnShelfOrTakeDownType
=
InterFunction
<
{
goodsIds
:
number
[];
status
:
number
},
any
>
;
//商品-单个上下架(新)
export
type
upOrDownShelfType
=
InterFunction
<
{
id
:
number
;
status
:
number
},
any
>
;
//商品批量删除
export
type
batchRemoveWareInfoType
=
InterFunction
<
number
[],
any
>
;
//商品-单个删除
export
type
removeMallGoodsType
=
InterFunction
<
{
id
:
number
},
any
>
;
//商品-上下移动
export
type
exchangeGoodsInfoType
=
InterFunction
<
{
firstId
:
number
;
secondId
:
number
},
any
>
;
//商品-新增(新)
export
type
addMallGoodsType
=
InterFunction
<
{
categoryPrimaryId
:
number
;
categorySubId
:
number
;
description
:
string
;
goodsDetails
:
string
;
goodsLabel
:
string
;
goodsSpecList
:
{
chooseType
:
number
;
goodsSpecValuesList
:
{
channelPrice
?:
number
;
id
:
any
;
partNo
:
string
;
salePrice
:
number
;
showPrice
:
number
;
specValueImage
:
string
;
specValueName
:
string
;
stock
?:
number
;
goodsSpecId
?:
number
;
}[];
id
:
any
;
mallGoodsId
:
number
;
must
:
number
;
skuUnitId
:
number
;
specName
:
string
;
}[];
labelShow
:
number
;
resourcesList
:
{
id
:
number
;
type
:
number
;
url
:
string
;
}[];
shelfStatus
:
number
;
tradeName
:
string
;
},
any
>
;
//商品-编辑(新)
export
type
editMallGoodsType
=
InterFunction
<
{
categoryPrimaryId
:
number
;
categorySubId
:
number
;
description
:
string
;
goodsDetails
:
string
;
goodsLabel
:
string
;
goodsSpecList
:
{
chooseType
:
number
;
goodsSpecValuesList
:
{
channelPrice
?:
number
;
id
:
any
;
partNo
:
string
;
salePrice
:
number
;
showPrice
:
number
;
specValueImage
:
string
;
specValueName
:
string
;
stock
?:
number
;
goodsSpecId
:
number
;
}[];
id
:
any
;
mallGoodsId
:
number
;
must
:
number
;
skuUnitId
:
number
;
specName
:
string
;
}[];
id
:
number
;
labelShow
:
number
;
resourcesList
:
{
id
:
number
;
type
:
number
;
url
:
string
;
}[];
shelfStatus
:
number
;
tradeName
:
string
;
},
any
>
;
//商品-列表(新)
export
type
listPageGoodsInfoType
=
InterItemFunction
<
{
categoryPrimaryId
?:
number
;
tradeName
?:
string
;
shelfStatus
?:
number
},
{
categoryPrimaryId
:
number
;
categorySubId
:
number
;
createTime
:
string
;
description
:
string
;
goodsDetails
:
string
;
goodsLabel
:
string
;
goodsSpecList
:
{
chooseType
:
number
;
goodsSpecValuesList
:
{
channelPrice
:
number
;
goodsSpecId
:
number
;
id
:
number
;
partNo
:
string
;
salePrice
:
number
;
showPrice
:
number
;
specValueImage
:
string
;
specValueName
:
string
;
stock
:
number
;
}[];
id
:
number
;
mallGoodsId
:
number
;
must
:
number
;
skuUnitId
:
number
;
specName
:
string
;
}[];
id
:
number
;
labelShow
:
number
;
resourcesList
:
{
id
:
number
;
type
:
number
;
url
:
string
;
}[];
shelfStatus
:
number
;
tradeName
:
string
;
userAccountId
:
number
;
}[]
>
;
//商城-详情(新)
export
type
mallGoodsDetailsType
=
InterFunction
<
{
id
:
number
},
{
categoryPrimaryId
:
number
;
categorySubId
:
number
;
createTime
:
string
;
description
:
string
;
goodsDetails
:
string
;
goodsLabel
:
string
;
goodsSpecList
:
{
chooseType
:
number
;
goodsSpecValuesList
:
{
channelPrice
:
number
;
goodsSpecId
:
number
;
id
:
number
;
partNo
:
string
;
salePrice
:
number
;
showPrice
:
number
;
specValueImage
:
string
;
specValueName
:
string
;
stock
:
number
;
}[];
id
:
number
;
mallGoodsId
:
number
;
must
:
number
;
skuUnitId
:
number
;
specName
:
string
;
}[];
id
:
number
;
labelShow
:
number
;
resourcesList
:
{
id
:
number
;
type
:
number
;
url
:
string
;
}[];
shelfStatus
:
number
;
tradeName
:
string
;
userAccountId
:
number
;
}
>
;
src/api/interface/systemManageType.ts
浏览文件 @
3018428e
...
...
@@ -130,6 +130,8 @@ export type listCompanyPage = InterListFunction<
phoneNum
:
string
;
province
:
string
;
remark
:
string
;
lat
:
number
;
lon
:
number
;
}
>
;
// 单位-新增
...
...
@@ -147,6 +149,8 @@ export type listCompanyAdd = InterFunction<
province
?:
string
;
remark
?:
string
;
area
?:
string
[];
lat
:
number
;
lon
:
number
;
},
NonNullable
<
unknown
>
>
;
...
...
@@ -165,6 +169,8 @@ export type listCompanyUpdate = InterFunction<
province
?:
string
;
remark
?:
string
;
area
?:
string
[];
lat
:
number
;
lon
:
number
;
},
NonNullable
<
unknown
>
>
;
...
...
@@ -184,6 +190,82 @@ export type listCompanyRemove = InterFunction<
},
NonNullable
<
unknown
>
>
;
//单位-详情
export
type
getCompanyInfoByIdType
=
InterFunction
<
{
id
:
number
},
{
address
:
string
;
city
:
string
;
companyName
:
string
;
companyType
:
number
;
companyUserName
:
string
;
district
:
string
;
fullName
:
string
;
id
:
number
;
phoneNum
:
string
;
province
:
string
;
remark
:
string
;
}
>
;
//单位-成员列表
export
type
listCompanyMembersType
=
InterItemFunction
<
{
companyInfoId
:
number
},
{
accountStatus
:
number
;
accountType
:
number
;
companyAuthStatus
:
number
;
companyName
:
string
;
cooperationTagVOS
:
{
createTime
:
string
;
id
:
number
;
tagDescription
:
string
;
tagImg
:
string
;
tagName
:
string
;
tagRequire
:
string
;
}[];
createTime
:
string
;
deleted
:
number
;
email
:
string
;
id
:
number
;
inviteCount
:
number
;
leader
:
number
;
nickName
:
string
;
phoneNum
:
string
;
portType
:
number
;
realNameAuthStatus
:
number
;
remark
:
string
;
source
:
number
;
uid
:
string
;
userImg
:
string
;
userName
:
string
;
userRcdVO
:
{
createTime
:
string
;
id
:
number
;
rcdNickname
:
string
;
rcdUserId
:
number
;
rcdUserName
:
string
;
remark
:
string
;
userAccountId
:
number
;
};
userSex
:
number
;
}[]
>
;
//单位-成员绑定
export
type
bindingCompanyMemberType
=
InterFunction
<
{
companyInfoId
:
number
;
userAccountId
:
number
},
any
>
;
//单位-成员解绑
export
type
unbindCompanyMemberType
=
InterFunction
<
{
companyInfoId
:
number
;
userAccountId
:
number
},
any
>
;
//单位-管理员转让
export
type
transferLeaderType
=
InterFunction
<
{
companyInfoId
:
number
;
fromUserAccountId
:
number
;
toUserAccountId
:
number
},
any
>
;
//账号权限-列表
export
type
listRoleInfoPageType
=
InterItemFunction
<
{
numberOrName
?:
string
},
...
...
src/api/modules/categoryManage.ts
浏览文件 @
3018428e
import
axios
from
'../request'
;
import
{
addPrimaryCategoryType
,
addSubCategoryType
,
categoryDetailsType
,
categoryListRespType
,
categoryListType
,
categoryRelevantType
,
deletePrimaryCategoryType
,
deleteSubCategoryType
,
directoryListType
,
directoryPageListType
,
exchangeType
,
updatePrimaryCategoryType
,
updateSubCategoryType
,
}
from
'~/api/interface/categoryManage'
;
export
class
CategoryManageAPI
{
...
...
@@ -97,4 +105,28 @@ export class CategoryManageAPI {
static
getRelevantBusiness
:
categoryRelevantType
=
(
params
)
=>
{
return
axios
.
get
(
'/pms/classify/queryRelevantBusiness'
,
{
params
});
};
// 分类管理-分类列表(新)
static
getCategoryRespList
:
categoryListRespType
=
(
data
)
=>
axios
.
post
(
'/pms/category/categoryList'
,
data
);
// 分类管理-1级分类新增(新)
static
addPrimaryCategory
:
addPrimaryCategoryType
=
(
data
)
=>
axios
.
post
(
'/pms/category/addPrimaryCategory'
,
data
);
// 分类管理-1级分类编辑(新)
static
updatePrimaryCategory
:
updatePrimaryCategoryType
=
(
data
)
=>
axios
.
post
(
'/pms/category/updatePrimaryCategory'
,
data
);
// 分类管理-1级分类删除(新)
static
deletePrimaryCategory
:
deletePrimaryCategoryType
=
(
params
)
=>
axios
.
get
(
'/pms/category/deletePrimaryCategory'
,
{
params
});
//分类管理-1级分类交换顺序
static
exchangeCategory
:
exchangeType
=
(
data
)
=>
axios
.
post
(
'/pms/category/exchange'
,
data
);
// 分类管理-2级分类新增(新)
static
addSubCategory
:
addSubCategoryType
=
(
data
)
=>
axios
.
post
(
'/pms/category/addSubCategory'
,
data
);
// 分类管理-2级分类编辑(新)
static
updateSubCategory
:
updateSubCategoryType
=
(
data
)
=>
axios
.
post
(
'/pms/category/updateSubCategory'
,
data
);
// 分类管理-2级分类删除(新)
static
deleteSubCategory
:
deleteSubCategoryType
=
(
params
)
=>
axios
.
get
(
'/pms/category/deleteSubCategory'
,
{
params
});
}
src/api/modules/common.ts
浏览文件 @
3018428e
import
axios
from
'../request'
;
import
{
appletQRCodeType
,
BackEndLoginType
,
batchRemoveBannerInfo
,
exchangeBannerInfo
,
getLoginInfoType
,
getUserAccountByPhoneNumType
,
insertBannerInfo
,
insertModuleInfo
,
listBannerInfoPage
,
...
...
@@ -70,4 +73,15 @@ export class CommonAPI {
// V1.0.1-banner-排序交换
static
exchangeBannerInfo
:
exchangeBannerInfo
=
(
params
)
=>
axios
.
post
(
'/release/module/exchangeBannerInfo'
,
params
);
//手机号筛选小程序用户
static
getUserAccountByPhoneNum
:
getUserAccountByPhoneNumType
=
(
params
)
=>
axios
.
get
(
'/userapp/user-account/getUserAccountByPhoneNum'
,
{
params
});
//获取小程序二维码
static
getAppletQRCode
:
appletQRCodeType
=
(
params
)
=>
{
return
axios
.
get
(
'/userapp/wx/getAppletQRCode'
,
{
params
});
};
//获取登录信息
static
getLoginInfo
:
getLoginInfoType
=
(
params
)
=>
axios
.
get
(
'/userapp/temp-auth/getLoginInfo'
,
{
params
});
}
src/api/modules/goodsAPI.ts
浏览文件 @
3018428e
import
{
addGoodsType
,
addMallGoodsType
,
batchOnShelfOrTakeDownType
,
batchRemoveWareInfoType
,
detailGoodsType
,
editGoodsType
,
editMallGoodsType
,
exchangeGoodsInfoType
,
listGoodsType
,
listPageGoodsInfoType
,
mallGoodsDetailsType
,
otherServiceType
,
removeMallGoodsType
,
skuUnitType
,
upOrDownShelfType
,
}
from
'~/api/interface/goodsType'
;
import
axios
from
'../request'
;
...
...
@@ -30,7 +36,7 @@ class GoodsAPI {
};
// 商品-单位
static
getSkuUnit
:
skuUnitType
=
()
=>
{
return
axios
.
get
(
'/pms/goods/getSkuUnit'
);
return
axios
.
get
(
'/pms/
mall/
goods/getSkuUnit'
);
};
// 商品-其它服务列表
static
getOtherServiceList
:
otherServiceType
=
()
=>
{
...
...
@@ -40,13 +46,35 @@ class GoodsAPI {
static
batchOnShelfOrTakeDown
:
batchOnShelfOrTakeDownType
=
(
data
)
=>
{
return
axios
.
post
(
'/pms/goods/batchOnShelfOrTakeDown'
,
data
);
};
//商品-单个上下架(新)
static
upOrDownShelf
:
upOrDownShelfType
=
(
params
)
=>
axios
.
get
(
'/pms/mall/goods/upOrDownShelf'
,
{
params
});
// 商品-批量删除
static
batchRemoveWareInfo
:
batchRemoveWareInfoType
=
(
data
)
=>
{
return
axios
.
post
(
'/pms/goods/batchRemoveWareInfo'
,
data
);
};
//商品-单个删除
static
removeMallGoods
:
removeMallGoodsType
=
(
params
)
=>
axios
.
get
(
'/pms/mall/goods/removeMallGoods'
,
{
params
});
// 商品-上下移动
static
exchangeGoodsInfo
:
exchangeGoodsInfoType
=
(
params
)
=>
{
return
axios
.
get
(
'/pms/goods/exchangeGoodsInfo'
,
{
params
});
};
//商品-上下移动
static
exchange
:
exchangeGoodsInfoType
=
(
params
)
=>
axios
.
get
(
'/pms/mall/goods/exchange'
,
{
params
});
// 商品-新增(新)
static
addMallGoods
:
addMallGoodsType
=
(
data
)
=>
axios
.
post
(
'/pms/mall/goods/addMallGoods'
,
data
);
//商品-编辑(新)
static
editMallGoods
:
editMallGoodsType
=
(
data
)
=>
axios
.
post
(
'/pms/mall/goods/editMallGoods'
,
data
);
// 商品-列表(新)
static
getListPageGoodsInfo
:
listPageGoodsInfoType
=
(
data
)
=>
axios
.
post
(
'/pms/mall/goods/listPageGoodsInfo'
,
data
);
// 商品-详情(新)
static
getMallGoodsDetails
:
mallGoodsDetailsType
=
(
params
)
=>
axios
.
get
(
'/pms/mall/goods/mallGoodsDetails'
,
{
params
});
}
export
default
GoodsAPI
;
src/api/modules/systemManage.ts
浏览文件 @
3018428e
import
{
bindingCompanyMemberType
,
deleteRoleInfoType
,
getCompanyInfoByIdType
,
getSecondDistrictInfo
,
insertBAccountType
,
insertRoleInfoType
,
listBAccountPageType
,
listCompanyAdd
,
listCompanyMembersType
,
listCompanyPage
,
listCompanyRemove
,
listCompanyUpdate
,
...
...
@@ -12,6 +15,8 @@ import {
listRoleInfoPageType
,
listRoleMenuInfoType
,
removeBAccountType
,
transferLeaderType
,
unbindCompanyMemberType
,
updateBAccountType
,
updatePasswordType
,
updateRoleInfoType
,
...
...
@@ -58,10 +63,25 @@ export class SystemManageAPI {
// 单位-删除
static
listCompanyRemove
:
listCompanyRemove
=
(
params
)
=>
axios
.
get
(
'/userapp/company/remove'
,
{
params
});
//单位-详情
static
getCompanyInfoById
:
getCompanyInfoByIdType
=
(
params
)
=>
axios
.
get
(
'/userapp/company/getCompanyInfoById'
,
{
params
});
// 单位-区域
static
getSecondDistrictInfo
:
getSecondDistrictInfo
=
(
params
)
=>
axios
.
get
(
'/pms/webDevice/getSecondDistrictInfo'
,
{
params
});
//单位-成员列表
static
getListCompanyMembers
:
listCompanyMembersType
=
(
params
)
=>
axios
.
get
(
'/userapp/company/listCompanyMembers'
,
{
params
});
//单位-成员绑定
static
bindingCompanyMember
:
bindingCompanyMemberType
=
(
params
)
=>
axios
.
get
(
'/userapp/company/bindingCompanyMember'
,
{
params
});
//单位-成员解除绑定
static
unbindCompanyMember
:
unbindCompanyMemberType
=
(
params
)
=>
axios
.
get
(
'/userapp/company/unbindCompanyMember'
,
{
params
});
//单位-管理员转让
static
transferLeader
:
transferLeaderType
=
(
params
)
=>
axios
.
get
(
'/userapp/company/transferLeader'
,
{
params
});
//账号权限-列表
static
getListRoleInfoPage
:
listRoleInfoPageType
=
(
data
)
=>
...
...
src/api/request.ts
浏览文件 @
3018428e
...
...
@@ -36,7 +36,7 @@ service.interceptors.response.use(
// 当接口返回正常时执行
if
(
status
===
200
)
{
// 如果不报错就直接返回数据
if
(
data
.
code
===
'200'
)
{
if
(
[
'200'
,
'7002'
].
includes
(
data
.
code
)
)
{
return
Promise
.
resolve
(
data
);
}
// 重新登录?
...
...
src/assets/image/qr-code-icon.svg
0 → 100644
浏览文件 @
3018428e
<svg
width=
"50"
height=
"50"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
><defs><filter
x=
"-5.7%"
y=
"-8.7%"
width=
"112.4%"
height=
"117.4%"
filterUnits=
"objectBoundingBox"
id=
"a"
><feOffset
dx=
"2"
in=
"SourceAlpha"
result=
"shadowOffsetOuter1"
/><feGaussianBlur
stdDeviation=
"7.5"
in=
"shadowOffsetOuter1"
result=
"shadowBlurOuter1"
/><feColorMatrix
values=
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"
in=
"shadowBlurOuter1"
/></filter><path
d=
"M2 0h327.586a1 1 0 01.707.293l49.414 49.414a1 1 0 01.293.707V268a2 2 0 01-2 2H2a2 2 0 01-2-2V2a2 2 0 012-2z"
id=
"b"
/></defs><g
transform=
"translate(-330)"
fill=
"none"
fill-rule=
"evenodd"
><rect
fill=
"#FFF"
width=
"380"
height=
"270"
rx=
"2"
/><path
d=
"M366.833 10.833v2.334h2.334v-2.334h-2.334zm-7 16.334h2.334V29.5h-2.334v-2.333zm9.334-9.334h2.333v2.334h-2.333v-2.334zm-9.334 4.667h2.334v2.333h-2.334V22.5zm4.667-4.667h2.333v2.334H364.5v-2.334zM351.667 8.5H361c.644 0 1.167.522 1.167 1.167V19c0 .644-.523 1.167-1.167 1.167h-9.333A1.167 1.167 0 01350.5 19V9.667c0-.645.522-1.167 1.167-1.167zm1.166 2.333v7h7v-7h-7zm2.334 2.334h2.333V15.5h-2.333v-2.333zm10.5-4.667h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167V9.667c0-.645.522-1.167 1.167-1.167zm0 14h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167v-4.666c0-.645.522-1.167 1.167-1.167zm1.166 2.333v2.334h2.334v-2.334h-2.334zM351.667 22.5h4.666c.645 0 1.167.522 1.167 1.167v4.666c0 .645-.522 1.167-1.167 1.167h-4.666a1.167 1.167 0 01-1.167-1.167v-4.666c0-.645.522-1.167 1.167-1.167zm1.166 2.333v2.334h2.334v-2.334h-2.334z"
opacity=
".5"
fill=
"#000"
fill-opacity=
".9"
/><use
fill=
"#000"
filter=
"url(#a)"
xlink:href=
"#b"
/><use
fill=
"#FFF"
xlink:href=
"#b"
/></g></svg>
\ No newline at end of file
src/components/EditableCell/index.tsx
浏览文件 @
3018428e
import
{
Form
,
InputNumber
,
Input
,
Select
}
from
'antd'
;
import
{
Form
,
InputNumber
,
Input
,
Select
,
Radio
}
from
'antd'
;
import
React
from
'react'
;
import
{
Uploader
}
from
'~/components/uploader'
;
import
{
UploadOutlined
}
from
'@ant-design/icons'
;
...
...
@@ -8,7 +8,7 @@ export interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
editing
:
boolean
;
dataIndex
:
string
;
title
:
any
;
inputType
:
'number'
|
'text'
|
'select'
|
'uploader'
;
inputType
:
'number'
|
'text'
|
'select'
|
'uploader'
|
'radio'
|
'textArea'
;
record
:
any
;
index
:
number
;
children
:
React
.
ReactNode
;
...
...
@@ -16,8 +16,10 @@ export interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
const
EditableCell
:
React
.
FC
<
EditableCellProps
&
{
selectOption
?:
{
name
:
string
;
id
:
number
}[];
radioOption
?:
{
name
:
string
;
id
:
number
}[];
uploadSuccess
?:
(
record
:
any
,
result
:
any
)
=>
void
;
rules
?:
any
;
maxLength
?:
number
;
}
>
=
({
editing
,
...
...
@@ -27,15 +29,17 @@ const EditableCell: React.FC<
record
,
index
,
selectOption
,
radioOption
,
uploadSuccess
,
children
,
rules
,
maxLength
,
...
restProps
})
=>
{
const
inputNode
=
()
=>
{
switch
(
inputType
)
{
case
'number'
:
return
<
InputNumber
/>;
return
<
InputNumber
placeholder=
{
`请输入${title}`
}
maxLength=
{
maxLength
}
/>;
case
'select'
:
return
(
<
Select
placeholder=
{
`请选择${title}`
}
style=
{
{
textAlign
:
'start'
}
}
>
...
...
@@ -58,8 +62,20 @@ const EditableCell: React.FC<
<
UploadOutlined
/>
</
Uploader
>
);
case
'radio'
:
return
(
<
Radio
.
Group
>
{
radioOption
?.
map
((
v
)
=>
(
<
Radio
value=
{
v
.
id
}
key=
{
v
.
id
}
>
{
v
.
name
}
</
Radio
>
))
}
</
Radio
.
Group
>
);
case
'textArea'
:
return
<
Input
.
TextArea
placeholder=
{
`请输入${title}`
}
maxLength=
{
maxLength
}
showCount
/>;
default
:
return
<
Input
placeholder=
{
`请输入${title}`
}
/>;
return
<
Input
placeholder=
{
`请输入${title}`
}
maxLength=
{
maxLength
}
/>;
}
};
return
(
...
...
src/components/layout/index.scss
浏览文件 @
3018428e
...
...
@@ -113,6 +113,7 @@ $page-background: #f3f6ff;
.logo-img
{
width
:
32px
;
height
:
32px
;
border-radius
:
4px
;
}
.logo-text
{
...
...
src/components/layout/title/index.tsx
浏览文件 @
3018428e
...
...
@@ -5,7 +5,6 @@ import { Button, Dropdown, MenuProps, Modal } from 'antd';
import
Logo
from
'../../../assets/icon/logo_big.png'
;
import
'./index.scss'
;
import
{
REMOVE_MENU
,
REMOVE_MENU_ID
,
SET_COLLAPSE
}
from
'~/store/module/menu'
;
import
{
REMOVE_ROLE_ID
}
from
'~/store/module/userInfo'
;
import
{
useDispatch
,
useSelector
}
from
'react-redux'
;
import
{
useNavigate
}
from
'react-router-dom'
;
import
Cookies
from
'js-cookie'
;
...
...
@@ -42,7 +41,6 @@ export function TitleView() {
Cookies
.
remove
(
'SHAREFLY-TOKEN'
);
dispatch
(
REMOVE_MENU
());
dispatch
(
REMOVE_MENU_ID
());
dispatch
(
REMOVE_ROLE_ID
());
},
});
}
}
...
...
@@ -62,8 +60,8 @@ export function TitleView() {
}
}
>
<
div
className=
'layout-logo'
>
<
img
className=
'logo-img'
src=
{
Logo
}
alt=
'云享飞'
/>
<
div
className=
'logo-text'
>
云享飞后台管理
</
div
>
<
img
src=
{
userInfo
.
companyInfoVO
.
brandLogo
||
Logo
}
className=
'logo-img'
alt=
'云享飞'
/>
<
div
className=
'logo-text'
>
{
userInfo
.
companyInfoVO
.
brandName
||
'云享飞管理后台'
}
</
div
>
<
div
onClick=
{
setMenuCollapsed
}
>
<
svg
className=
{
`hamburger ${isActive ? 'is-active' : ''}`
}
...
...
src/pages/categoryManage/categoryList/components/addOrEditCategoryModal/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
Form
,
Input
,
message
,
Modal
,
ModalProps
}
from
'antd'
;
import
{
FC
,
useEffect
,
useState
}
from
'react'
;
import
{
Uploader
}
from
'~/components/uploader'
;
import
{
UploadOutlined
}
from
'@ant-design/icons'
;
import
{
InterDataType
,
InterReqType
}
from
'~/api/interface'
;
import
{
addPrimaryCategoryType
,
categoryListRespType
}
from
'~/api/interface/categoryManage'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
//分类列表返回类型
type
categoryType
=
InterDataType
<
categoryListRespType
>
[
'list'
];
//新增分类请求参数类型
type
addPrimaryCategoryParameter
=
InterReqType
<
addPrimaryCategoryType
>
;
interface
selfProps
{
onCancel
:
()
=>
void
;
onOK
:
()
=>
void
;
currentCategory
:
categoryType
[
0
]
|
undefined
;
}
const
AddOrEditCategoryModal
:
FC
<
ModalProps
&
selfProps
>
=
({
open
,
onCancel
,
onOK
,
currentCategory
,
})
=>
{
const
[
form
]
=
Form
.
useForm
<
addPrimaryCategoryParameter
>
();
const
[
fileList
,
setFileList
]
=
useState
<
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[]
>
([]);
//上传成功
const
uploadSuccess
=
(
value
:
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[],
)
=>
{
form
.
setFieldValue
(
'icon'
,
value
[
0
].
url
);
setFileList
([...
value
]);
};
//提交
const
handleOk
=
()
=>
{
form
.
validateFields
().
then
((
values
:
any
)
=>
{
CategoryManageAPI
[
currentCategory
?
'updatePrimaryCategory'
:
'addPrimaryCategory'
]({
...
values
,
id
:
currentCategory
?
currentCategory
.
id
:
undefined
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'新增成功'
);
form
.
resetFields
();
setFileList
([]);
onOK
();
}
});
});
};
const
handleCancel
=
()
=>
{
form
.
resetFields
();
setFileList
([]);
onCancel
();
};
useEffect
(()
=>
{
if
(
currentCategory
)
{
form
.
setFieldsValue
({
name
:
currentCategory
.
name
,
icon
:
currentCategory
.
icon
,
description
:
currentCategory
.
description
||
undefined
,
});
setFileList
([
{
name
:
'categoryImg'
,
id
:
Math
.
random
(),
uid
:
Math
.
random
(),
url
:
currentCategory
.
icon
,
},
]);
}
},
[
currentCategory
]);
return
(
<
Modal
open=
{
open
}
title=
{
currentCategory
?
'编辑分类'
:
'新增分类'
}
onCancel=
{
handleCancel
}
onOk=
{
handleOk
}
>
<
Form
wrapperCol=
{
{
span
:
16
}
}
labelCol=
{
{
span
:
4
}
}
form=
{
form
}
>
<
Form
.
Item
label=
'分类名称'
name=
'name'
rules=
{
[{
required
:
true
,
message
:
'请输入分类名称'
}]
}
>
<
Input
placeholder=
'请输入分类名称'
maxLength=
{
15
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'分类图标'
name=
'icon'
rules=
{
[{
required
:
true
,
message
:
'请上传分类图标'
}]
}
>
<
Uploader
fileUpload
listType=
'picture-card'
onChange=
{
uploadSuccess
}
fileLength=
{
1
}
fileSize=
{
5
}
defaultFileList=
{
fileList
}
>
<
UploadOutlined
/>
</
Uploader
>
</
Form
.
Item
>
<
Form
.
Item
label=
'分类描述'
name=
'description'
>
<
Input
.
TextArea
placeholder=
'请输入分类描述'
rows=
{
4
}
maxLength=
{
70
}
showCount
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
AddOrEditCategoryModal
;
src/pages/categoryManage/categoryList/index.scss
0 → 100644
浏览文件 @
3018428e
.category-list
{
&
-row-bg
{
td
{
background-color
:
rgba
(
$color
:
#000000
,
$alpha
:
0
.1
)
!
important
;
}
}
}
src/pages/categoryManage/categoryList/index.tsx
0 → 100644
浏览文件 @
3018428e
import
SearchBox
from
'~/components/search-box'
;
import
{
Button
,
Form
,
Image
,
message
,
Modal
,
Radio
,
Table
,
Tooltip
}
from
'antd'
;
import
{
ArrowDownOutlined
,
ArrowUpOutlined
,
DownOutlined
,
PlusOutlined
,
RightOutlined
,
}
from
'@ant-design/icons'
;
import
{
categoryListRespType
}
from
'~/api/interface/categoryManage'
;
import
{
useEffect
,
useState
}
from
'react'
;
import
{
InterDataType
,
PaginationProps
}
from
'~/api/interface'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
EditableCell
from
'~/components/EditableCell'
;
import
AddOrEditCategoryModal
from
'./components/addOrEditCategoryModal'
;
import
'./index.scss'
;
import
_
from
'lodash'
;
type
EditableTableProps
=
Parameters
<
typeof
Table
>
[
0
];
type
ColumnTypes
=
Exclude
<
EditableTableProps
[
'columns'
],
undefined
>
;
//分类列表返回类型
type
categoryType
=
InterDataType
<
categoryListRespType
>
[
'list'
];
const
CategoryList
=
()
=>
{
const
[
categoryTableForm
]
=
Form
.
useForm
<
any
>
();
const
[
selectedRowKeys
,
setSelectedRowKeys
]
=
useState
<
React
.
Key
[]
>
([]);
//新增,编辑分类弹窗
const
[
addOrEditCategoryModalShow
,
setAddOrEditCategoryModalShow
]
=
useState
<
boolean
>
(
false
);
const
[
currentCategory
,
setCurrentCategory
]
=
useState
<
categoryType
[
0
]
>
();
const
[
loading
,
setLoading
]
=
useState
<
boolean
>
(
false
);
// 编辑的行
const
[
editingKey
,
setEditingKey
]
=
useState
<
number
[]
>
([]);
//展开的行
const
[
expandedRowKeys
,
setExpandedRowKeys
]
=
useState
<
number
[]
>
([]);
const
tableColumns
:
(
ColumnTypes
[
number
]
&
{
editable
?:
boolean
;
dataIndex
?:
string
;
rules
?:
any
;
maxLength
?:
number
;
inputType
?:
string
;
})[]
=
[
{
title
:
'分类名称'
,
dataIndex
:
'name'
,
editable
:
true
,
width
:
'20%'
,
ellipsis
:
true
,
onHeaderCell
:
()
=>
({
style
:
{
textAlign
:
'center'
,
},
}),
rules
:
[{
required
:
true
,
message
:
'请输入分类名称'
}],
maxLength
:
15
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
span
style=
{
{
marginLeft
:
record
.
subDTOList
&&
record
.
subDTOList
.
length
!=
0
?
'10px'
:
'24px'
,
}
}
>
{
text
}
</
span
>
),
},
{
title
:
'图片'
,
align
:
'center'
,
dataIndex
:
'icon'
,
render
:
(
url
:
string
)
=>
(
url
?
<
Image
src=
{
url
}
width=
{
40
}
height=
{
40
}
/>
:
''
),
},
{
title
:
'描述'
,
align
:
'center'
,
dataIndex
:
'description'
,
editable
:
true
,
width
:
'20%'
,
ellipsis
:
true
,
maxLength
:
70
,
inputType
:
'textArea'
,
render
:
(
text
:
string
)
=>
(
<
Tooltip
placement=
'topLeft'
title=
{
<
span
>
{
text
}
</
span
>
}
>
<
span
>
{
text
}
</
span
>
</
Tooltip
>
),
},
{
title
:
'创建时间'
,
align
:
'center'
,
dataIndex
:
'createTime'
,
},
{
title
:
'操作'
,
onHeaderCell
:
()
=>
({
style
:
{
textAlign
:
'center'
,
},
}),
onCell
:
()
=>
({
style
:
{
textAlign
:
'right'
,
},
}),
render
:
(
_text
:
string
,
record
:
any
)
=>
editingKey
.
some
((
id
:
number
)
=>
id
===
record
.
id
)
?
(
<>
<
Button
type=
'link'
onClick=
{
()
=>
addChildCategorySubmit
(
record
)
}
>
确定
</
Button
>
<
Button
type=
'link'
onClick=
{
()
=>
addChildCategoryCancel
(
record
)
}
>
取消
</
Button
>
</>
)
:
(
<>
{
record
.
subDTOList
?
(
<
Button
type=
'link'
onClick=
{
()
=>
addChildrenCategory
(
record
)
}
>
新增子分类
</
Button
>
)
:
(
''
)
}
<
Button
type=
'link'
onClick=
{
()
=>
addOrEditCategoryModalShowClick
(
record
)
}
>
编辑
</
Button
>
<
Button
type=
'link'
danger
onClick=
{
()
=>
deleteCategory
(
record
)
}
>
删除
</
Button
>
</>
),
},
];
const
mergedColumns
=
tableColumns
.
map
((
col
:
any
)
=>
{
if
(
!
col
.
editable
)
{
return
col
;
}
return
{
...
col
,
onCell
:
(
record
:
categoryType
[
0
],
index
:
number
)
=>
({
record
,
index
,
dataIndex
:
col
.
dataIndex
,
title
:
col
.
title
,
editing
:
editingKey
.
some
((
id
:
number
)
=>
id
===
record
.
id
),
rules
:
col
.
rules
,
maxLength
:
col
.
maxLength
,
inputType
:
col
.
inputType
,
}),
};
});
const
[
tableData
,
setTableData
]
=
useState
<
categoryType
>
([]);
const
[
allTableData
,
setAllTableData
]
=
useState
<
categoryType
>
([]);
//分页
const
[
pagination
,
setPagination
]
=
useState
<
PaginationProps
&
{
totalCount
:
number
}
>
({
pageNo
:
1
,
pageSize
:
10
,
totalCount
:
0
,
});
//获取分类列表
const
getCategoryList
=
(
query
?:
PaginationProps
,
isAll
?:
boolean
)
=>
{
setLoading
(
true
);
CategoryManageAPI
.
getCategoryRespList
({
pageNo
:
pagination
.
pageNo
,
pageSize
:
pagination
.
pageSize
,
...
query
,
}).
then
(({
result
})
=>
{
setLoading
(
false
);
if
(
isAll
)
{
setAllTableData
(
result
.
list
?
[...
result
.
list
]
:
[]);
}
else
{
setTableData
(
result
.
list
?
[...
result
.
list
]
:
[]);
pagination
.
totalCount
=
result
.
totalCount
;
setPagination
(
pagination
);
}
});
};
const
paginationChange
=
(
pageNo
:
number
,
pageSize
:
number
)
=>
{
pagination
.
pageNo
=
pageNo
;
pagination
.
pageSize
=
pageSize
;
getCategoryList
();
};
// 排序选择
const
onSelectChange
=
(
record
:
categoryType
[
0
])
=>
{
setSelectedRowKeys
([
record
.
id
]);
};
//新增、编辑分类弹窗
const
addOrEditCategoryModalShowClick
=
(
record
?:
categoryType
[
0
]
|
any
)
=>
{
if
(
record
&&
!
record
.
subDTOList
)
{
setEditingKey
([...
editingKey
,
record
.
id
]);
const
defaultFormVal
=
Object
.
getOwnPropertyNames
(
record
).
reduce
((
pre
:
any
,
cur
:
string
)
=>
{
if
([
'name'
,
'description'
].
includes
(
cur
))
{
pre
[
cur
+
record
.
id
]
=
record
[
cur
];
}
return
pre
;
},
{});
categoryTableForm
.
setFieldsValue
(
defaultFormVal
);
}
else
{
setAddOrEditCategoryModalShow
(
true
);
setCurrentCategory
(
record
?
{
...
record
}
:
undefined
);
}
};
const
addOrEditCategoryModalCancel
=
()
=>
{
setAddOrEditCategoryModalShow
(
false
);
};
const
addOrEditCategoryModalOk
=
()
=>
{
setAddOrEditCategoryModalShow
(
false
);
getCategoryList
();
};
//删除分类
const
deleteCategory
=
(
record
:
categoryType
[
0
])
=>
{
Modal
.
confirm
({
title
:
'分类删除'
,
content
:
'确认删除这条分类?'
,
onOk
:
()
=>
{
console
.
log
(
'当前数据-->'
,
record
);
CategoryManageAPI
[
record
.
subDTOList
?
'deletePrimaryCategory'
:
'deleteSubCategory'
]({
id
:
record
.
id
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'删除成功'
);
if
(
pagination
.
pageNo
!==
1
&&
tableData
.
length
===
1
)
{
pagination
.
pageNo
-=
1
;
}
getCategoryList
();
getCategoryList
({
pageNo
:
1
,
pageSize
:
99999
},
true
);
}
});
},
});
};
//新增子分类
const
addChildrenCategory
=
(
record
:
categoryType
[
0
])
=>
{
const
categoryItemIndex
=
tableData
.
findIndex
((
v
)
=>
v
.
id
===
record
.
id
);
if
(
categoryItemIndex
!==
-
1
)
{
const
selfChildId
:
number
=
Math
.
random
();
tableData
[
categoryItemIndex
].
subDTOList
=
[
...
tableData
[
categoryItemIndex
].
subDTOList
,
{
id
:
selfChildId
,
name
:
''
,
description
:
''
,
categoryPrimaryId
:
record
.
id
},
];
tableData
.
splice
(
categoryItemIndex
,
1
,
tableData
[
categoryItemIndex
]);
setTableData
([...
tableData
]);
setEditingKey
([...
editingKey
,
selfChildId
]);
}
const
isExpend
:
boolean
=
expandedRowKeys
.
some
((
key
:
number
)
=>
key
===
record
.
id
);
if
(
!
isExpend
)
{
setExpandedRowKeys
([...
expandedRowKeys
,
record
.
id
]);
}
};
// 展开监听
const
onExpand
=
(
_expanded
:
boolean
,
record
:
categoryType
[
0
])
=>
{
const
index
=
expandedRowKeys
.
findIndex
((
item
:
any
)
=>
item
===
record
.
id
);
if
(
index
!==
-
1
)
{
expandedRowKeys
.
splice
(
index
,
1
);
}
else
{
expandedRowKeys
.
push
(
record
.
id
);
}
setExpandedRowKeys
([...
expandedRowKeys
]);
};
//提交新增子分类
const
addChildCategorySubmit
=
(
record
:
categoryType
[
0
][
'subDTOList'
][
0
])
=>
{
categoryTableForm
.
validateFields
([
'description'
+
record
.
id
,
'name'
+
record
.
id
])
.
then
((
values
)
=>
{
CategoryManageAPI
[
record
.
name
?
'updateSubCategory'
:
'addSubCategory'
]({
categoryPrimaryId
:
record
.
categoryPrimaryId
,
name
:
values
[
'name'
+
record
.
id
],
description
:
values
[
'description'
+
record
.
id
],
id
:
record
.
name
?
record
.
id
:
undefined
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
record
.
name
?
'编辑子分类成功'
:
'新增子分类成功'
);
const
editingKeyIndex
=
editingKey
.
findIndex
((
id
)
=>
id
===
record
.
id
);
if
(
editingKeyIndex
!==
-
1
)
{
editingKey
.
splice
(
editingKeyIndex
,
1
);
setEditingKey
([...
editingKey
]);
getCategoryList
();
}
}
});
});
};
//取消新增子分类
const
addChildCategoryCancel
=
(
record
:
categoryType
[
0
][
'subDTOList'
][
0
])
=>
{
const
tableIndex
:
number
=
tableData
.
findIndex
((
v
)
=>
v
.
id
===
record
.
categoryPrimaryId
);
if
(
tableIndex
!==
-
1
)
{
const
subDTOIndex
:
number
=
tableData
[
tableIndex
].
subDTOList
.
findIndex
(
(
v
)
=>
v
.
id
===
record
.
id
,
);
if
(
subDTOIndex
!==
-
1
)
{
//新增下的取消
if
(
!
record
.
name
)
{
tableData
[
tableIndex
].
subDTOList
.
splice
(
subDTOIndex
,
1
);
tableData
.
splice
(
tableIndex
,
1
,
tableData
[
tableIndex
]);
setTableData
([...
tableData
]);
}
//新增、编辑下的取消
const
editKeyIndex
=
editingKey
.
findIndex
((
id
)
=>
id
===
record
.
id
);
editingKey
.
splice
(
editKeyIndex
,
1
);
setEditingKey
([...
editingKey
]);
//新增下的取消
if
(
tableData
[
tableIndex
].
subDTOList
.
length
===
0
&&
!
record
.
name
)
{
const
expandedRowKeysIndex
=
expandedRowKeys
.
findIndex
(
(
id
)
=>
id
===
record
.
categoryPrimaryId
,
);
expandedRowKeys
.
splice
(
expandedRowKeysIndex
,
1
);
setExpandedRowKeys
([...
expandedRowKeys
]);
}
}
}
};
// 切换排序
const
handleSort
=
_
.
debounce
(
async
(
from
:
'up'
|
'down'
)
=>
{
if
(
selectedRowKeys
.
length
===
0
)
{
message
.
warning
(
'请选择需要排序的数据'
).
then
();
return
;
}
// 当前选项
const
id
=
selectedRowKeys
.
at
(
-
1
);
// 当前索引
const
index
=
allTableData
.
findIndex
((
i
)
=>
i
.
id
===
id
);
// 当前表格中的索引
const
tableIndex
=
tableData
.
findIndex
((
i
)
=>
i
.
id
===
id
);
// 第一条数据不能上移
if
(
index
===
0
&&
from
===
'up'
)
{
message
.
warning
(
'已是第一条数据'
).
then
();
return
;
}
// 最后一条数据不能下移
if
(
index
===
allTableData
.
length
-
1
&&
from
===
'down'
)
{
message
.
warning
(
'已是最后一条数据'
).
then
();
return
;
}
// 转换位置
const
res
=
await
CategoryManageAPI
.
exchangeCategory
(
from
===
'up'
?
[
{
id
:
allTableData
[
index
-
1
].
id
,
sort
:
allTableData
[
index
-
1
].
sort
},
{
id
:
allTableData
[
index
].
id
,
sort
:
allTableData
[
index
].
sort
},
]
:
[
{
id
:
allTableData
[
index
+
1
].
id
,
sort
:
allTableData
[
index
+
1
].
sort
},
{
id
:
allTableData
[
index
].
id
,
sort
:
allTableData
[
index
].
sort
},
],
);
if
(
res
&&
res
.
code
===
'200'
)
{
message
.
success
(
'操作成功'
).
then
();
// 如果是当前页的第一条数据
if
(
tableIndex
===
0
&&
from
===
'up'
)
{
paginationChange
(
pagination
.
pageNo
-
1
,
pagination
.
pageSize
);
getCategoryList
({
pageNo
:
1
,
pageSize
:
9999
},
true
);
return
;
}
// 如果是当前页的最后一条数据
if
(
tableIndex
===
tableData
.
length
-
1
&&
from
===
'down'
)
{
paginationChange
(
pagination
.
pageNo
+
1
,
pagination
.
pageSize
);
getCategoryList
({
pageNo
:
1
,
pageSize
:
9999
},
true
);
return
;
}
paginationChange
(
pagination
.
pageNo
,
pagination
.
pageSize
);
getCategoryList
({
pageNo
:
1
,
pageSize
:
9999
},
true
);
}
},
500
);
//防抖
// const debounce:<T extends ()=>T>= (func: T, delay: number)=> {
// let timeout: NodeJS.Timeout;
//
// return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
// clearTimeout(timeout);
//
// timeout = setTimeout(() => {
// func.apply(this, args);
// }, delay);
// } as T;
// }
useEffect
(()
=>
{
getCategoryList
();
getCategoryList
({
pageNo
:
1
,
pageSize
:
99999
},
true
);
},
[]);
return
(
<
div
className=
'category-list'
>
<
SearchBox
child=
{
<>
<
Button
icon=
{
<
PlusOutlined
/>
}
type=
'primary'
onClick=
{
()
=>
addOrEditCategoryModalShowClick
()
}
>
新增分类
</
Button
>
<
Button
icon=
{
<
ArrowUpOutlined
/>
}
type=
'primary'
onClick=
{
()
=>
handleSort
(
'up'
)
}
></
Button
>
<
Button
icon=
{
<
ArrowDownOutlined
/>
}
type=
'primary'
onClick=
{
()
=>
handleSort
(
'down'
)
}
></
Button
>
</>
}
/>
<
Form
form=
{
categoryTableForm
}
component=
{
false
}
>
<
Table
bordered
rowSelection=
{
{
hideSelectAll
:
true
,
selectedRowKeys
,
renderCell
:
(
checked
:
boolean
,
record
:
categoryType
[
0
])
=>
{
console
.
log
(
'选中-->'
,
checked
);
return
(
<>
{
record
.
subDTOList
?
(
<
Radio
onChange=
{
()
=>
onSelectChange
(
record
)
}
checked=
{
checked
}
/>
)
:
(
''
)
}
</>
);
},
}
}
loading=
{
loading
}
rowKey=
'id'
columns=
{
mergedColumns
}
dataSource=
{
tableData
}
rowClassName=
{
(
record
:
categoryType
[
0
])
=>
{
if
(
record
.
subDTOList
)
{
return
''
;
}
return
'category-list-row-bg'
;
}
}
pagination=
{
{
total
:
pagination
.
totalCount
,
pageSize
:
pagination
.
pageSize
,
current
:
pagination
.
pageNo
,
showSizeChanger
:
true
,
showQuickJumper
:
true
,
onChange
:
(
page
:
number
,
pageSize
:
number
)
=>
paginationChange
(
page
,
pageSize
),
showTotal
:
(
total
,
range
)
=>
`当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`
,
}
}
components=
{
{
body
:
{
cell
:
EditableCell
,
},
}
}
expandedRowKeys=
{
expandedRowKeys
}
onExpand=
{
(
expanded
:
boolean
,
record
:
categoryType
[
0
])
=>
onExpand
(
expanded
,
record
)
}
expandable=
{
{
rowExpandable
:
(
record
)
=>
{
if
(
record
.
subDTOList
&&
record
.
subDTOList
.
length
!=
0
)
{
return
true
;
}
return
false
;
},
expandIcon
:
({
expanded
,
onExpand
,
record
})
=>
{
if
(
expanded
&&
record
.
subDTOList
&&
record
.
subDTOList
.
length
!=
0
)
{
return
<
DownOutlined
onClick=
{
(
e
)
=>
onExpand
(
record
,
e
)
}
/>;
}
if
(
record
.
subDTOList
&&
record
.
subDTOList
.
length
!=
0
)
{
return
<
RightOutlined
onClick=
{
(
e
)
=>
onExpand
(
record
,
e
)
}
/>;
}
return
<></>;
},
}
}
childrenColumnName=
'subDTOList'
/>
</
Form
>
{
/*新增,编辑分类*/
}
<
AddOrEditCategoryModal
open=
{
addOrEditCategoryModalShow
}
onCancel=
{
addOrEditCategoryModalCancel
}
onOK=
{
addOrEditCategoryModalOk
}
currentCategory=
{
currentCategory
}
/>
</
div
>
);
};
export
default
CategoryList
;
src/pages/common/login/index.scss
浏览文件 @
3018428e
...
...
@@ -17,8 +17,16 @@ body {
box-shadow
:
0px
20px
30px
rgba
(
112
,
158
,
254
,
0
.45
);
display
:
flex
;
flex-wrap
:
wrap
;
position
:
relative
;
.login-flex
{
flex
:
1
;
position
:
relative
;
.qr-code-wrap
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
}
.login-content
{
text-align
:
center
;
...
...
@@ -37,6 +45,7 @@ body {
color
:
rgba
(
0
,
0
,
0
,
0
.5
);
}
}
.login-form
{
.login-image
{
margin
:
62px
auto
46px
;
...
...
@@ -79,5 +88,16 @@ body {
box-shadow
:
3px
3px
30px
#dddddd
;
}
}
.qrCode-icon
{
position
:
absolute
;
top
:
0
;
right
:
0
;
}
.account-login-operate
{
position
:
absolute
;
top
:
10px
;
right
:
10px
;
}
}
}
src/pages/common/login/index.tsx
浏览文件 @
3018428e
import
{
Button
,
Checkbox
,
Form
,
I
nput
,
messag
e
}
from
'antd'
;
import
{
useEffect
}
from
'react'
;
import
{
Button
,
Checkbox
,
Form
,
I
mage
,
Input
,
message
,
QRCod
e
}
from
'antd'
;
import
{
useEffect
,
useState
}
from
'react'
;
import
{
LockOutlined
,
UserOutlined
}
from
'@ant-design/icons'
;
import
{
useNavigate
}
from
'react-router-dom'
;
import
Cookies
from
'js-cookie'
;
...
...
@@ -10,18 +10,27 @@ import { CommonAPI } from '~/api';
import
{
useDispatch
}
from
'react-redux'
;
import
{
SET_USERINFO
}
from
'~/store/module/userInfo'
;
import
{
authRouterList
}
from
'~/router'
;
import
qrCodeIcon
from
'~/assets/image/qr-code-icon.svg'
;
// 请求的类型
type
ReqType
=
InterReqType
<
BackEndLoginType
>
;
//定时器暂存
let
time
:
NodeJS
.
Timer
;
function
LoginView
()
{
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/ban-ts-comment
// @ts-ignore
const
navigate
=
useNavigate
();
// redux
const
dispatch
=
useDispatch
();
// 表单钩子
const
[
form
]
=
Form
.
useForm
<
ReqType
>
();
//是否二维码登录
const
[
isLoginCode
,
setIsLoginCode
]
=
useState
<
boolean
>
(
false
);
//获取小程序二维码唯一标识
const
[
randomLoginCode
]
=
useState
<
string
>
(
parseInt
(
String
(
Math
.
random
()
*
10001
),
10
)
+
''
);
//小程序二维码地址
const
[
qrCodeUrl
,
setQrCodeUrl
]
=
useState
<
string
>
(
''
);
// 提交数据
const
onFinish
=
async
(
values
:
ReqType
)
=>
{
const
res
=
await
CommonAPI
.
BackEndLogin
({
...
...
@@ -29,6 +38,7 @@ function LoginView() {
passWord
:
values
?.
passWord
,
});
if
(
res
&&
res
.
code
===
'200'
)
{
message
.
success
(
'登录成功'
);
const
{
token
}
=
res
.
result
;
await
Cookies
.
set
(
'SHAREFLY-TOKEN'
,
token
);
// 记住密码
...
...
@@ -49,7 +59,50 @@ function LoginView() {
message
.
error
(
'登录失败,请检查账号信息'
);
}
};
//显示二维码登录方式
const
changeLoginUseEvent
=
()
=>
{
//第一次二维码
if
(
!
isLoginCode
&&
!
qrCodeUrl
)
{
CommonAPI
.
getAppletQRCode
({
page
:
'page-identity/identity-empower/index'
,
scene
:
`randomLoginCode=
${
randomLoginCode
}
&port=1`
,
}).
then
(({
result
})
=>
{
setQrCodeUrl
(
result
?
`data:image/png;base64,
${
result
}
`
:
''
);
time
=
setInterval
(()
=>
{
getLoginInfo
();
},
1000
);
});
}
else
if
(
!
isLoginCode
&&
qrCodeUrl
)
{
time
=
setInterval
(()
=>
{
getLoginInfo
();
},
1000
);
}
else
{
if
(
time
)
{
clearInterval
(
time
);
}
}
setIsLoginCode
(
!
isLoginCode
);
};
//二维码登录
const
getLoginInfo
=
()
=>
{
CommonAPI
.
getLoginInfo
({
randomLoginCode
}).
then
(
async
({
result
,
code
})
=>
{
if
(
code
===
'200'
)
{
clearInterval
(
time
);
message
.
success
(
'登录成功'
);
const
{
token
}
=
result
;
await
Cookies
.
set
(
'SHAREFLY-TOKEN'
,
token
);
dispatch
(
SET_USERINFO
(
result
));
localStorage
.
setItem
(
'roleId'
,
result
.
roleInfo
.
id
.
toString
());
authRouterList
().
then
((
value
:
any
)
=>
{
if
(
value
.
length
)
{
navigate
({
pathname
:
value
[
0
].
children
.
find
((
v
:
any
)
=>
!
v
.
meta
.
hidden
)?.
path
});
}
else
{
message
.
warning
(
'请先配置权限'
);
}
});
}
});
};
// componentDidMount
useEffect
(()
=>
{
// 是否保存密码
...
...
@@ -62,65 +115,96 @@ function LoginView() {
remember
:
Boolean
(
Cookies
.
get
(
'remember'
)),
});
},
[]);
return
(
<
div
className=
'login-warp'
>
<
div
className=
'login-view'
>
<
div
className=
'login-flex login-content'
>
<
div
className=
'login-title'
>
欢迎来到
</
div
>
<
div
className=
'login-text'
>
科比特 ·
云享飞管理平台
</
div
>
<
div
className=
'login-title'
></
div
>
<
div
className=
'login-text'
>
云享飞管理平台
</
div
>
<
div
className=
'login-detail'
>
让天空为世界所用
</
div
>
</
div
>
<
div
className=
'login-flex login-form'
>
<
div
className=
'login-image'
/>
<
div
className=
'login-input'
>
<
Form
name=
'basic'
form=
{
form
}
wrapperCol=
{
{
span
:
16
,
offset
:
4
}
}
initialValues=
{
{
remember
:
true
}
}
onFinish=
{
onFinish
}
autoComplete=
'off'
>
<
Form
.
Item
name=
'accountNo'
rules=
{
[{
required
:
true
,
message
:
'请输入用户名'
}]
}
>
<
Input
size=
'large'
prefix=
{
<
UserOutlined
/>
}
placeholder=
'请输入账号'
allowClear
/>
</
Form
.
Item
>
{
isLoginCode
?
(
<
div
className=
'qr-code-wrap'
>
{
qrCodeUrl
?
(
<
Image
src=
{
qrCodeUrl
}
alt=
''
width=
{
200
}
height=
{
200
}
preview=
{
false
}
/>
)
:
(
<
QRCode
value=
'https://ant.design/'
status=
'loading'
/>
)
}
</
div
>
)
:
(
<>
<
div
className=
'login-image'
/>
<
div
className=
'login-input'
>
<
Form
name=
'basic'
form=
{
form
}
wrapperCol=
{
{
span
:
16
,
offset
:
4
}
}
initialValues=
{
{
remember
:
true
}
}
onFinish=
{
onFinish
}
autoComplete=
'off'
>
<
Form
.
Item
name=
'accountNo'
rules=
{
[{
required
:
true
,
message
:
'请输入用户名'
}]
}
>
<
Input
size=
'large'
prefix=
{
<
UserOutlined
/>
}
placeholder=
'请输入账号'
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
name=
'passWord'
className=
'login-password'
rules=
{
[{
required
:
true
,
message
:
'请输入密码'
}]
}
>
<
Input
.
Password
size=
'large'
prefix=
{
<
LockOutlined
/>
}
placeholder=
'请输入密码'
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
name=
'passWord'
className=
'login-password'
rules=
{
[{
required
:
true
,
message
:
'请输入密码'
}]
}
>
<
Input
.
Password
size=
'large'
prefix=
{
<
LockOutlined
/>
}
placeholder=
'请输入密码'
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
name=
'remember'
className=
'login-remember'
valuePropName=
'checked'
wrapperCol=
{
{
offset
:
4
,
span
:
8
}
}
>
<
Checkbox
>
记住密码
</
Checkbox
>
</
Form
.
Item
>
<
Form
.
Item
name=
'remember'
className=
'login-remember'
valuePropName=
'checked'
wrapperCol=
{
{
offset
:
4
,
span
:
8
}
}
>
<
Checkbox
>
记住密码
</
Checkbox
>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
offset
:
7
,
span
:
15
}
}
>
<
Button
type=
'primary'
htmlType=
'submit'
shape=
'round'
size=
'large'
className=
'login-submit'
>
登录
</
Button
>
</
Form
.
Item
>
</
Form
>
</
div
>
<
Form
.
Item
wrapperCol=
{
{
offset
:
7
,
span
:
15
}
}
>
<
Button
type=
'primary'
htmlType=
'submit'
shape=
'round'
size=
'large'
className=
'login-submit'
>
登录
</
Button
>
</
Form
.
Item
>
</
Form
>
</
div
>
</>
)
}
</
div
>
{
isLoginCode
?
(
<
div
className=
'account-login-operate'
>
<
Button
type=
'link'
onClick=
{
changeLoginUseEvent
}
>
使用账号登录
</
Button
>
</
div
>
)
:
(
<
div
className=
'qrCode-icon'
>
<
img
src=
{
qrCodeIcon
}
alt=
'icon'
onClick=
{
changeLoginUseEvent
}
/>
</
div
>
)
}
</
div
>
</
div
>
);
...
...
src/pages/customManage/customList/index.tsx
浏览文件 @
3018428e
...
...
@@ -239,7 +239,7 @@ function CustomListView() {
label: '手机号',
name: 'phoneNum',
type: 'input',
placeholder: '请输入
用户账
号',
placeholder: '请输入
手机
号',
},
{
label: '来源',
...
...
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/components/baseInfo/index.scss
0 → 100644
浏览文件 @
3018428e
.goods-video-wrap
{
position
:
relative
;
width
:
200px
;
img
{
position
:
absolute
;
right
:
0
;
top
:
0
;
transform
:
translate
(
50%
,-
25%
);
}
}
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/components/baseInfo/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
Button
,
Cascader
,
Form
,
Input
,
Radio
,
Select
}
from
'antd'
;
import
{
Uploader
}
from
'~/components/uploader'
;
import
type
{
RadioChangeEvent
}
from
'antd'
;
import
{
UploadOutlined
}
from
'@ant-design/icons'
;
import
React
,
{
forwardRef
,
useEffect
,
useImperativeHandle
,
useState
}
from
'react'
;
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
categoryListRespType
}
from
'~/api/interface/categoryManage'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
deletePng
from
'~/assets/image/delete.png'
;
import
'./index.scss'
;
//分类返回类型
type
categoryType
=
InterDataType
<
categoryListRespType
>
[
'list'
];
interface
selfProps
{
ref
:
any
;
}
//基本信息表单类型
export
type
baseInfoType
=
{
tradeName
:
string
;
description
:
string
;
mainImgList
:
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[];
subImgList
:
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[];
videoList
:
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[];
categoryId
:
number
[];
shelfStatus
:
number
;
labelShow
:
number
;
goodsLabel
:
string
;
};
const
BaseInfo
=
forwardRef
<
any
,
selfProps
>
((
_props
,
ref
)
=>
{
const
[
baseInfoForm
]
=
Form
.
useForm
<
baseInfoType
>
();
const
[
labelShow
,
setLabelShow
]
=
useState
<
boolean
>
(
false
);
//分类列表
const
[
categoryList
,
setCategoryList
]
=
useState
<
categoryType
>
([]);
//主图
const
[
mainFileList
,
setMainFileList
]
=
useState
<
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[]
>
([]);
//副图
const
[
subFileList
,
setSubFileList
]
=
useState
<
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[]
>
([]);
//视频
const
[
videoFileList
,
setVideoFileList
]
=
useState
<
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[]
>
([]);
useImperativeHandle
(
ref
,
()
=>
({
getForm
:
()
=>
baseInfoForm
,
setLabelShow
:
(
value
:
boolean
)
=>
setLabelShow
(
value
),
mediaData
:
{
setMainFileList
,
setSubFileList
,
setVideoFileList
,
},
}));
//标签选中监听
const
labelRadioChange
=
(
e
:
RadioChangeEvent
)
=>
{
setLabelShow
(
!!
e
.
target
.
value
);
};
//上传结果
const
uploadSuccess
=
(
fileList
:
{
id
:
number
;
name
:
string
;
uid
:
number
;
url
:
string
;
}[],
type
:
string
,
)
=>
{
switch
(
type
)
{
case
'mainImgList'
:
setMainFileList
(
fileList
);
baseInfoForm
.
setFieldValue
(
'mainImgList'
,
fileList
);
break
;
case
'subImgList'
:
setSubFileList
(
fileList
);
baseInfoForm
.
setFieldValue
(
'subImgList'
,
fileList
);
break
;
case
'videoList'
:
setVideoFileList
(
fileList
);
baseInfoForm
.
setFieldValue
(
'videoList'
,
fileList
);
break
;
default
:
break
;
}
};
//分类列表
const
getCategoryList
=
()
=>
{
CategoryManageAPI
.
getCategoryRespList
({
pageNo
:
1
,
pageSize
:
99999
}).
then
(({
result
})
=>
{
setCategoryList
(
result
.
list
||
[]);
});
};
//视频删除
const
deleteVideo
=
()
=>
{
setVideoFileList
([]);
baseInfoForm
.
setFieldValue
(
'videoList'
,
undefined
);
};
useEffect
(()
=>
{
getCategoryList
();
},
[]);
return
(
<
div
className=
'base-info'
>
<
Form
labelCol=
{
{
span
:
2
}
}
wrapperCol=
{
{
span
:
8
}
}
form=
{
baseInfoForm
}
initialValues=
{
{
labelShow
:
0
,
shelfStatus
:
1
}
}
>
<
Form
.
Item
label=
'商品名称'
name=
'tradeName'
rules=
{
[{
required
:
true
,
message
:
'请输入商品名称'
}]
}
>
<
Input
placeholder=
'请输入商品名称'
maxLength=
{
50
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'商品描述'
name=
'description'
rules=
{
[{
required
:
true
,
message
:
'请输入商品描述'
}]
}
>
<
Input
.
TextArea
rows=
{
4
}
placeholder=
'请输入商品描述'
maxLength=
{
70
}
showCount
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'商品主图'
name=
'mainImgList'
rules=
{
[{
required
:
true
,
message
:
'请上传商品主图'
}]
}
>
<
Uploader
fileUpload
listType=
'picture-card'
onChange=
{
(
fileList
)
=>
uploadSuccess
(
fileList
,
'mainImgList'
)
}
defaultFileList=
{
mainFileList
}
>
<
UploadOutlined
/>
</
Uploader
>
</
Form
.
Item
>
<
Form
.
Item
label=
'商品副图'
name=
'subImgList'
>
<
Uploader
fileUpload
listType=
'picture-card'
onChange=
{
(
fileList
)
=>
uploadSuccess
(
fileList
,
'subImgList'
)
}
defaultFileList=
{
subFileList
}
fileLength=
{
4
}
>
<
UploadOutlined
/>
</
Uploader
>
</
Form
.
Item
>
<
Form
.
Item
label=
'商品视频'
name=
'videoList'
>
{
videoFileList
.
length
?
(
<
div
className=
'goods-video-wrap'
>
<
video
src=
{
videoFileList
[
0
].
url
}
style=
{
{
width
:
'200px'
,
height
:
'200px'
}
}
controls
/>
<
img
src=
{
deletePng
}
alt=
'删除'
onClick=
{
deleteVideo
}
/>
</
div
>
)
:
(
<
Uploader
fileUpload
listType=
'text'
onChange=
{
(
fileList
)
=>
uploadSuccess
(
fileList
,
'videoList'
)
}
defaultFileList=
{
videoFileList
}
fileType=
{
[
'video/mp4'
,
'video/avi'
,
'video/wmv'
,
'video/rmvb'
]
}
fileSize=
{
50
}
>
<
Button
icon=
{
<
UploadOutlined
/>
}
>
上传视频
</
Button
>
</
Uploader
>
)
}
</
Form
.
Item
>
<
Form
.
Item
label=
'商品分类'
name=
'categoryId'
rules=
{
[{
required
:
true
,
message
:
'请选择商品分类'
}]
}
>
<
Cascader
placeholder=
'请选择商品分类'
options=
{
categoryList
}
fieldNames=
{
{
label
:
'name'
,
value
:
'id'
,
children
:
'subDTOList'
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'商品状态'
name=
'shelfStatus'
rules=
{
[{
required
:
true
,
message
:
'请选择商品状态'
}]
}
>
<
Select
placeholder=
'请选择商品状态'
>
<
Select
.
Option
value=
{
1
}
>
上架
</
Select
.
Option
>
<
Select
.
Option
value=
{
0
}
>
下架
</
Select
.
Option
>
</
Select
>
</
Form
.
Item
>
<
Form
.
Item
label=
'显示标签'
name=
'labelShow'
>
<
Radio
.
Group
onChange=
{
labelRadioChange
}
>
<
Radio
value=
{
1
}
>
显示
</
Radio
>
<
Radio
value=
{
0
}
>
不显示
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
{
labelShow
?
(
<
Form
.
Item
label=
'商品标签'
name=
'goodsLabel'
rules=
{
[{
required
:
true
,
message
:
'请输入商品标签'
}]
}
>
<
Input
placeholder=
'请输入商品标签'
maxLength=
{
10
}
/>
</
Form
.
Item
>
)
:
(
''
)
}
</
Form
>
</
div
>
);
});
export
default
BaseInfo
;
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/components/introduceInfo/index.tsx
0 → 100644
浏览文件 @
3018428e
import
RichText
from
'~/components/richText'
;
import
{
FC
}
from
'react'
;
interface
selfProps
{
onChange
:
(
html
:
string
)
=>
void
;
introduceInfo
:
string
;
}
const
IntroduceInfo
:
FC
<
selfProps
>
=
({
onChange
,
introduceInfo
})
=>
{
//富文本修改
const
richTextOnChange
=
(
html
?:
string
)
=>
{
onChange
(
html
||
''
);
};
return
(
<
div
className=
'introduce-info'
>
<
RichText
richTextContent=
{
introduceInfo
}
height=
{
400
}
onChange=
{
richTextOnChange
}
/>
</
div
>
);
};
export
default
IntroduceInfo
;
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/components/skuAddOrEditModal/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
Button
,
Form
,
Input
,
Modal
,
ModalProps
,
Radio
,
Select
,
Table
}
from
'antd'
;
import
{
FC
,
useEffect
,
useState
}
from
'react'
;
import
EditableCell
from
'~/components/EditableCell'
;
import
{
MinusOutlined
,
PlusOutlined
}
from
'@ant-design/icons'
;
import
{
InterDataType
,
InterReqType
}
from
'~/api/interface'
;
import
{
addMallGoodsType
,
skuUnitType
}
from
'~/api/interface/goodsType'
;
import
{
filterObjAttr
}
from
'~/utils'
;
import
{
isEmptyBol
,
regPriceNumber
}
from
'~/utils/validateUtils'
;
type
EditableTableProps
=
Parameters
<
typeof
Table
>
[
0
];
type
ColumnTypes
=
Exclude
<
EditableTableProps
[
'columns'
],
undefined
>
;
//商品sku规格类型
type
goodsSpecType
=
Exclude
<
InterReqType
<
addMallGoodsType
>
,
undefined
>
[
'goodsSpecList'
][
0
];
//商品sku规格值类型
type
goodsSpecValuesType
=
Exclude
<
InterReqType
<
addMallGoodsType
>
,
undefined
>
[
'goodsSpecList'
][
0
][
'goodsSpecValuesList'
][
0
]
&
{
fileList
:
any
};
//单位返回类型
type
unitType
=
InterDataType
<
skuUnitType
>
;
interface
selfProps
{
onCancel
:
()
=>
void
;
onHandleOk
:
(
value
:
goodsSpecType
)
=>
void
;
skuUnitList
:
unitType
;
currentSku
:
goodsSpecType
|
undefined
;
}
const
SkuAddOrEditModal
:
FC
<
ModalProps
&
selfProps
>
=
({
open
,
onCancel
,
onHandleOk
,
skuUnitList
,
currentSku
,
})
=>
{
const
[
goodsSpecForm
]
=
Form
.
useForm
<
Omit
<
goodsSpecType
,
'goodsSpecValuesList'
>>
();
const
[
goodsSpecValuesForm
]
=
Form
.
useForm
<
goodsSpecValuesType
>
();
//销售正则价格校验
const
salePriceValidator
=
(
_rules
:
any
,
value
:
number
)
=>
{
if
(
!
isEmptyBol
(
value
))
{
if
(
regPriceNumber
(
value
.
toString
()))
{
if
(
value
>
99999999
||
value
<
0
)
{
return
Promise
.
reject
(
new
Error
(
'价格最大为99999999且大于0'
));
}
return
Promise
.
resolve
();
}
else
{
return
Promise
.
reject
(
new
Error
(
'为整数且最多保留两位小数'
));
}
}
else
{
return
Promise
.
reject
(
new
Error
(
'请输入销售价'
));
}
};
//渠道正则价格校验
const
channelPriceValidator
=
(
_rules
:
any
,
value
:
number
)
=>
{
if
(
!
isEmptyBol
(
value
))
{
if
(
regPriceNumber
(
value
.
toString
()))
{
if
(
value
>
99999999
||
value
<
0
)
{
return
Promise
.
reject
(
new
Error
(
'价格最大为99999999且大于0'
));
}
return
Promise
.
resolve
();
}
else
{
return
Promise
.
reject
(
new
Error
(
'为整数且最多保留两位小数'
));
}
}
else
{
return
Promise
.
resolve
();
}
};
//库存正则校验
const
stockPriceValidator
=
(
_rules
:
any
,
value
:
number
)
=>
{
if
(
!
isEmptyBol
(
value
))
{
if
(
/^
[
+
]{0,1}(\d
+
)
$/
.
test
(
value
.
toString
()))
{
if
(
value
>
99999999
||
value
<
0
)
{
return
Promise
.
reject
(
new
Error
(
'库存最大为99999999且大于0'
));
}
return
Promise
.
resolve
();
}
else
{
return
Promise
.
reject
(
new
Error
(
'请输入正整数'
));
}
}
else
{
return
Promise
.
reject
(
new
Error
(
'请输入库存'
));
}
};
const
[
tableData
,
setTableData
]
=
useState
<
goodsSpecValuesType
[]
>
([
{
id
:
Math
.
random
(),
channelPrice
:
0
,
partNo
:
''
,
salePrice
:
0
,
showPrice
:
1
,
specValueImage
:
''
,
specValueName
:
''
,
stock
:
0
,
fileList
:
[],
},
]);
const
defaultColumns
:
(
ColumnTypes
[
number
]
&
{
editable
?:
boolean
;
dataIndex
?:
string
;
inputType
?:
string
;
radioOption
?:
{
name
:
string
;
id
:
number
}[];
rules
?:
any
;
maxLength
?:
number
;
})[]
=
[
{
title
:
'序号'
,
align
:
'center'
,
width
:
'5%'
,
render
:
(
_text
:
string
,
_record
:
any
,
index
:
number
)
=>
index
+
1
,
},
{
title
:
'图片'
,
align
:
'center'
,
editable
:
true
,
dataIndex
:
'specValueImage'
,
inputType
:
'uploader'
,
},
{
title
:
'选项名称'
,
align
:
'center'
,
editable
:
true
,
dataIndex
:
'specValueName'
,
rules
:
[{
required
:
true
,
message
:
'请输入选项名称'
}],
maxLength
:
30
,
},
{
title
:
'料号'
,
align
:
'center'
,
editable
:
true
,
dataIndex
:
'partNo'
,
maxLength
:
30
,
},
{
title
:
'销售价'
,
align
:
'center'
,
editable
:
true
,
dataIndex
:
'salePrice'
,
rules
:
[{
required
:
true
,
validator
:
salePriceValidator
}],
inputType
:
'number'
,
},
{
title
:
'渠道价'
,
editable
:
true
,
align
:
'center'
,
dataIndex
:
'channelPrice'
,
rules
:
[{
required
:
false
,
validator
:
channelPriceValidator
}],
inputType
:
'number'
,
},
{
title
:
'库存'
,
editable
:
true
,
align
:
'center'
,
dataIndex
:
'stock'
,
rules
:
[{
required
:
true
,
validator
:
stockPriceValidator
}],
inputType
:
'number'
,
},
{
title
:
'是否显示'
,
editable
:
true
,
align
:
'center'
,
dataIndex
:
'showPrice'
,
inputType
:
'radio'
,
width
:
'18%'
,
radioOption
:
[
{
id
:
1
,
name
:
'显示'
},
{
id
:
0
,
name
:
'不显示'
},
],
},
{
title
:
'操作'
,
align
:
'center'
,
width
:
'10%'
,
render
:
(
_text
:
string
,
_record
:
any
,
index
:
number
)
=>
(
<>
{
tableData
.
length
-
1
===
index
?
(
<
Button
type=
'primary'
icon=
{
<
PlusOutlined
/>
}
onClick=
{
addSkuDataRowClick
}
style=
{
{
marginRight
:
'10px'
}
}
></
Button
>
)
:
(
''
)
}
{
index
?
(
<
Button
type=
'primary'
icon=
{
<
MinusOutlined
/>
}
onClick=
{
()
=>
removeSkuDataRowClick
(
index
)
}
></
Button
>
)
:
(
''
)
}
</>
),
},
];
const
columns
=
defaultColumns
.
map
((
col
)
=>
{
if
(
!
col
.
editable
)
{
return
col
;
}
return
{
...
col
,
onCell
:
(
record
:
any
)
=>
({
record
,
dataIndex
:
col
.
dataIndex
,
title
:
col
.
title
,
editing
:
col
.
editable
,
radioOption
:
col
.
radioOption
,
inputType
:
col
.
inputType
,
uploadSuccess
:
col
.
inputType
===
'uploader'
?
uploadSuccess
:
undefined
,
rules
:
col
.
rules
,
}),
};
});
const
handleCancel
=
()
=>
{
clearForm
();
onCancel
();
};
const
clearForm
=
()
=>
{
goodsSpecForm
.
resetFields
();
goodsSpecValuesForm
.
resetFields
();
const
list
=
[
{
id
:
Math
.
random
(),
channelPrice
:
0
,
partNo
:
''
,
salePrice
:
0
,
showPrice
:
1
,
specValueImage
:
''
,
specValueName
:
''
,
stock
:
0
,
fileList
:
[],
},
];
const
obj
=
list
.
reduce
((
pre
:
any
,
cur
:
any
)
=>
{
Object
.
getOwnPropertyNames
(
cur
).
forEach
((
key
:
string
)
=>
{
if
([
'showPrice'
].
includes
(
key
))
{
pre
[
key
+
cur
.
id
]
=
cur
[
key
];
}
});
return
pre
;
},
{});
goodsSpecValuesForm
.
setFieldsValue
(
obj
);
setTableData
(
list
);
};
//新增一行规格值
const
addSkuDataRowClick
=
()
=>
{
const
list
=
[
...
tableData
,
{
id
:
Math
.
random
(),
channelPrice
:
0
,
partNo
:
''
,
salePrice
:
0
,
showPrice
:
1
,
specValueImage
:
''
,
specValueName
:
''
,
stock
:
0
,
fileList
:
[],
},
];
setTableData
(
list
);
const
obj
=
list
.
reduce
((
pre
:
any
,
cur
:
any
)
=>
{
Object
.
getOwnPropertyNames
(
cur
).
forEach
((
key
:
string
)
=>
{
if
([
'showPrice'
].
includes
(
key
))
{
pre
[
key
+
cur
.
id
]
=
cur
[
key
];
}
});
return
pre
;
},
{});
goodsSpecValuesForm
.
setFieldsValue
(
obj
);
};
//移除一行规格值
const
removeSkuDataRowClick
=
(
index
:
number
)
=>
{
tableData
.
splice
(
index
,
1
);
setTableData
([...
tableData
]);
};
//规格值上传图片返回
const
uploadSuccess
=
(
record
:
goodsSpecValuesType
,
value
:
any
)
=>
{
const
tableIndex
:
number
=
tableData
.
findIndex
((
v
)
=>
v
.
id
===
record
.
id
);
goodsSpecValuesForm
.
setFieldValue
(
'specValueImage'
+
record
.
id
,
value
.
length
?
value
[
0
].
url
:
undefined
,
);
if
(
tableIndex
!==
-
1
)
{
tableData
[
tableIndex
].
fileList
=
value
;
setTableData
([...
tableData
]);
}
};
//提交
const
handleOk
=
()
=>
{
Promise
.
all
([
goodsSpecForm
.
validateFields
(),
goodsSpecValuesForm
.
validateFields
()]).
then
(
(
values
:
any
)
=>
{
const
goodsSpecValuesList
:
goodsSpecValuesType
[]
=
tableData
.
map
((
v
)
=>
{
return
Object
.
getOwnPropertyNames
(
v
).
reduce
((
pre
:
any
,
cur
:
string
)
=>
{
if
(
Object
.
getOwnPropertyNames
(
values
[
1
]).
includes
(
cur
+
v
.
id
))
{
pre
[
cur
]
=
values
[
1
][
cur
+
v
.
id
];
pre
.
id
=
v
.
id
;
}
return
pre
;
},
{});
});
onHandleOk
({
...
values
[
0
],
goodsSpecValuesList
,
id
:
currentSku
?.
id
||
Math
.
random
()
});
clearForm
();
},
);
};
useEffect
(()
=>
{
const
obj
=
tableData
.
reduce
((
pre
:
any
,
cur
:
any
)
=>
{
Object
.
getOwnPropertyNames
(
cur
).
forEach
((
key
:
string
)
=>
{
if
([
'showPrice'
].
includes
(
key
))
{
pre
[
key
+
cur
.
id
]
=
cur
[
key
];
}
});
return
pre
;
},
{});
goodsSpecValuesForm
.
setFieldsValue
(
obj
);
if
(
currentSku
)
{
goodsSpecForm
.
setFieldsValue
(
filterObjAttr
(
currentSku
,
[
'goodsSpecValuesList'
]));
setTableData
(
currentSku
.
goodsSpecValuesList
.
map
((
v
:
any
)
=>
({
...
v
,
fileList
:
v
.
specValueImage
?
[
{
id
:
Math
.
random
(),
uid
:
Math
.
random
(),
url
:
v
.
specValueImage
,
name
:
'specValueImage'
,
},
]
:
[],
})),
);
const
goodsSpecValuesObj
=
currentSku
.
goodsSpecValuesList
.
reduce
((
pre
:
any
,
cur
:
any
)
=>
{
Object
.
getOwnPropertyNames
(
cur
)
.
filter
((
key
:
string
)
=>
key
!==
'id'
)
.
forEach
((
key
:
string
)
=>
{
pre
[
key
+
cur
.
id
]
=
cur
[
key
];
});
return
pre
;
},
{});
goodsSpecValuesForm
.
setFieldsValue
(
goodsSpecValuesObj
);
}
},
[
currentSku
]);
return
(
<
Modal
open=
{
open
}
title=
{
currentSku
?
'编辑规格'
:
'添加规格'
}
width=
{
1100
}
onCancel=
{
handleCancel
}
onOk=
{
handleOk
}
>
<
Form
labelCol=
{
{
span
:
2
}
}
wrapperCol=
{
{
span
:
22
}
}
initialValues=
{
{
chooseType
:
0
,
must
:
0
,
skuUnitId
:
skuUnitList
[
0
]?.
id
||
undefined
}
}
form=
{
goodsSpecForm
}
>
<
Form
.
Item
label=
'规格名称'
name=
'specName'
rules=
{
[{
required
:
true
,
message
:
'请输入规格名称'
}]
}
>
<
Input
placeholder=
'请输入规格名称'
maxLength=
{
30
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'规格值'
>
<
Form
component=
{
false
}
form=
{
goodsSpecValuesForm
}
>
<
Table
rowKey=
'id'
columns=
{
columns
as
ColumnTypes
}
components=
{
{
body
:
{
cell
:
EditableCell
,
},
}
}
bordered
dataSource=
{
tableData
}
pagination=
{
false
}
></
Table
>
</
Form
>
</
Form
.
Item
>
<
Form
.
Item
label=
'选择方式'
name=
'chooseType'
>
<
Radio
.
Group
>
<
Radio
value=
{
0
}
>
单选
</
Radio
>
<
Radio
value=
{
1
}
>
多选
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
'是否必选'
name=
'must'
>
<
Radio
.
Group
>
<
Radio
value=
{
0
}
>
非必选
</
Radio
>
<
Radio
value=
{
1
}
>
必选
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
'规格单位'
name=
'skuUnitId'
rules=
{
[{
required
:
true
,
message
:
'请选择规格单位'
}]
}
>
<
Select
placeholder=
'请选择规格单位'
>
{
skuUnitList
.
map
((
v
)
=>
(
<
Select
.
Option
value=
{
v
.
id
}
key=
{
v
.
id
}
>
{
v
.
unitName
}
</
Select
.
Option
>
))
}
</
Select
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
SkuAddOrEditModal
;
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/components/skuInfo/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
Button
,
Popconfirm
,
Table
,
Tag
}
from
'antd'
;
import
{
PlusOutlined
}
from
'@ant-design/icons'
;
import
{
ColumnsType
}
from
'antd/es/table'
;
import
{
FC
,
useState
}
from
'react'
;
import
{
InterDataType
,
InterReqType
,
PaginationProps
}
from
'~/api/interface'
;
import
{
addMallGoodsType
,
skuUnitType
}
from
'~/api/interface/goodsType'
;
//商品sku规格类型
type
goodsSpecType
=
Exclude
<
InterReqType
<
addMallGoodsType
>
,
undefined
>
[
'goodsSpecList'
][
0
];
//单位返回类型
type
unitType
=
InterDataType
<
skuUnitType
>
;
interface
selfProps
{
addOrEditSkuClick
:
()
=>
void
;
skuTableData
:
goodsSpecType
[];
skuUnitList
:
unitType
;
deleteSkuClick
:
(
record
:
goodsSpecType
)
=>
void
;
editSkuClick
:
(
record
:
goodsSpecType
)
=>
void
;
}
const
SkuInfo
:
FC
<
selfProps
>
=
({
addOrEditSkuClick
,
skuTableData
,
skuUnitList
,
deleteSkuClick
,
editSkuClick
,
})
=>
{
const
tableColumns
:
ColumnsType
<
goodsSpecType
>
=
[
{
title
:
'序号'
,
align
:
'center'
,
render
:
(
_text
:
string
,
_record
,
index
:
number
)
=>
index
+
1
,
},
{
title
:
'规格名称'
,
align
:
'center'
,
dataIndex
:
'specName'
,
},
{
title
:
'选择方式'
,
align
:
'center'
,
dataIndex
:
'chooseType'
,
render
:
(
text
:
number
)
=>
(
text
?
'多选'
:
'单选'
),
},
{
title
:
'是否必选'
,
align
:
'center'
,
dataIndex
:
'must'
,
render
:
(
text
:
number
)
=>
(
text
?
'必选'
:
'非必选'
),
},
{
title
:
'规格单位'
,
align
:
'center'
,
dataIndex
:
'skuUnitId'
,
render
:
(
text
:
number
)
=>
skuUnitList
.
find
((
v
)
=>
v
.
id
===
text
)?.
unitName
||
''
,
},
{
title
:
'规格值'
,
align
:
'center'
,
dataIndex
:
'goodsSpecValuesList'
,
render
:
(
text
:
goodsSpecType
[
'goodsSpecValuesList'
])
=>
text
.
map
((
v
)
=>
(
<
Tag
key=
{
v
.
id
}
>
{
v
.
specValueName
}
{
v
.
partNo
?
`(${v.partNo})`
:
''
}
</
Tag
>
)),
},
{
title
:
'操作'
,
align
:
'center'
,
render
:
(
_text
:
string
,
record
)
=>
(
<>
<
Button
type=
'link'
onClick=
{
()
=>
editSkuClick
(
record
)
}
>
编辑
</
Button
>
<
Popconfirm
placement=
'topLeft'
title=
{
'删除规格'
}
description=
{
'确认删除该规格吗?'
}
onConfirm=
{
()
=>
deleteSkuClick
(
record
)
}
okText=
'确定'
cancelText=
'取消'
>
<
Button
type=
'link'
danger
>
删除
</
Button
>
</
Popconfirm
>
</>
),
},
];
const
[
pagination
,
setPagination
]
=
useState
<
PaginationProps
>
({
pageNo
:
1
,
pageSize
:
10
,
});
//分页
const
paginationChange
=
(
pageNo
:
number
,
pageSize
:
number
)
=>
{
pagination
.
pageNo
=
pageNo
;
pagination
.
pageSize
=
pageSize
;
setPagination
({
...
pagination
});
};
return
(
<
div
className=
'sku-info'
>
<
div
className=
'sku-info-operate'
style=
{
{
margin
:
' 20px 0 '
}
}
>
<
Button
type=
'primary'
icon=
{
<
PlusOutlined
></
PlusOutlined
>
}
onClick=
{
()
=>
addOrEditSkuClick
()
}
>
添加规格
</
Button
>
</
div
>
<
Table
bordered
columns=
{
tableColumns
}
dataSource=
{
skuTableData
.
slice
(
(
pagination
.
pageNo
-
1
)
*
pagination
.
pageSize
,
pagination
.
pageNo
*
pagination
.
pageSize
,
)
}
rowKey=
'id'
pagination=
{
{
total
:
skuTableData
.
length
,
pageSize
:
pagination
.
pageSize
,
current
:
pagination
.
pageNo
,
showSizeChanger
:
true
,
showQuickJumper
:
true
,
onChange
:
(
page
:
number
,
pageSize
:
number
)
=>
paginationChange
(
page
,
pageSize
),
showTotal
:
(
total
,
range
)
=>
`当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`
,
}
}
/>
</
div
>
);
};
export
default
SkuInfo
;
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/index-old.tsx
0 → 100644
浏览文件 @
3018428e
import
BaseInfo
from
'~/components/goods/commonAddOrEdit/baseInfo'
;
import
StockSku
from
'~/components/goods/commonAddOrEdit/stockSku'
;
import
OtherInfo
from
'~/components/goods/commonAddOrEdit/otherInfo'
;
import
GoodsIntroduce
from
'~/components/goods/commonAddOrEdit/goodsIntroduce'
;
import
AddOrEditSkuModal
from
'~/components/goods/commonAddOrEdit/addOrEditSkuModal'
;
import
{
Button
,
message
}
from
'antd'
;
import
{
useNavigate
,
useSearchParams
}
from
'react-router-dom'
;
import
'./index.scss'
;
import
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
categoryListType
}
from
'~/api/interface/categoryManage'
;
import
{
customizeEntity
,
detailGoodsType
,
skuUnitType
,
specEntity
,
}
from
'~/api/interface/goodsType'
;
import
goodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
filterObjAttr
}
from
'~/utils'
;
import
GoodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
UploadFile
}
from
'antd/es/upload/interface'
;
//分类返回类型
type
categoryType
=
InterDataType
<
categoryListType
>
[
'list'
];
//产品-规格单位返回类型
type
unitType
=
InterDataType
<
skuUnitType
>
;
//商品返回类型
type
goodsDetailType
=
InterDataType
<
detailGoodsType
>
;
const
GoodsAddOrEditOrDetail
=
()
=>
{
const
[
searchParams
]
=
useSearchParams
();
//基本信息ref
const
baseInfoRef
=
useRef
<
any
>
();
const
navigate
=
useNavigate
();
//当前目录
const
[
currentDesc
,
setCurrentDesc
]
=
useState
<
number
>
(
-
1
);
//分类
const
[
categoryList
,
setCategoryList
]
=
useState
<
categoryType
>
([]);
//添加、编辑库存规格弹窗
const
[
addOrEditSkuModalShow
,
setAddOrEditSkuModalShow
]
=
useState
(
false
);
//库存规格数据
const
[
specData
,
setSpecData
]
=
useState
<
specEntity
[]
>
([]);
const
[
goodsSpecCopy
,
setGoodsSpecCopy
]
=
useState
<
specEntity
[]
>
([]);
//产品规格-单位
const
[
skuUnitList
,
setSkuUnitList
]
=
useState
<
unitType
>
([]);
//其它服务
const
[
otherService
,
setOtherService
]
=
useState
<
number
[]
>
([]);
// 当前操作行数据
const
[
curtRowData
,
setCurtRowData
]
=
useState
<
Partial
<
specEntity
>>
({});
//商品详情
const
[
goodsDetail
,
setGoodsDetail
]
=
useState
<
goodsDetailType
>
();
//产品介绍
const
[
productIntroduce
,
setProductIntroduce
]
=
useState
<
string
>
(
''
);
//是否商品详情
const
[
isDetail
,
setIsDetail
]
=
useState
<
boolean
>
(
false
);
//添加、编辑规格
const
addOrEditSkuShowEvent
=
(
record
?:
specEntity
)
=>
{
const
baseInfoForm
=
baseInfoRef
.
current
.
baseInform
;
setCurrentDesc
(
baseInfoForm
.
getFieldValue
(
'directoryId'
)
||
-
1
);
if
(
!
baseInfoForm
.
getFieldValue
(
'directoryId'
))
{
return
message
.
warning
(
'请先选择目录'
);
}
if
(
record
)
{
setCurtRowData
({
...
record
});
}
setAddOrEditSkuModalShow
(
true
);
};
//删除规格
const
deleteSkuEvent
=
(
record
:
specEntity
)
=>
{
const
index
=
specData
.
findIndex
((
v
)
=>
v
.
id
===
record
.
id
);
specData
.
splice
(
index
,
1
);
setSpecData
([...
specData
]);
};
const
addOrEditSkuModalCancel
=
()
=>
{
setAddOrEditSkuModalShow
(
false
);
setCurtRowData
({});
};
const
addOrEditSkuModalOk
=
(
data
:
specEntity
)
=>
{
if
(
Object
.
keys
(
curtRowData
).
length
!=
0
)
{
const
index
:
number
=
specData
.
findIndex
((
i
)
=>
i
.
id
===
data
.
id
);
specData
.
splice
(
index
,
1
,
data
);
setSpecData
([...
specData
]);
}
else
{
setSpecData
([...
specData
,
data
]);
}
addOrEditSkuModalCancel
();
};
//根据目录获取分类列表
const
getCategoryList
=
(
directoryId
:
number
)
=>
{
CategoryManageAPI
.
getCategoryList
({
directoryId
,
type
:
4
,
pageSize
:
9999
,
pageNo
:
1
}).
then
(
({
result
})
=>
{
setCategoryList
(
result
.
list
||
[]);
},
);
};
//产品-单位
const
getSkuUnit
=
()
=>
{
goodsAPI
.
getSkuUnit
().
then
(({
result
})
=>
{
setSkuUnitList
(
result
||
[]);
});
};
//其它服务选择
const
otherServiceSelect
=
(
ids
:
number
[])
=>
{
setOtherService
(
ids
);
};
//获取产品详情
const
getRichText
=
(
html
?:
string
)
=>
{
setProductIntroduce
(
html
||
''
);
};
//商品详情
const
getGoodsDetail
=
(
goodsInfoId
:
number
)
=>
{
GoodsAPI
.
getGoodsDetail
({
goodsInfoId
,
type
:
0
}).
then
(({
result
})
=>
{
setGoodsDetail
(
result
);
getCategoryList
(
result
.
directoryId
);
const
specList
:
specEntity
[]
=
result
.
goodsSpec
.
reduce
((
pre
:
any
,
cur
:
specEntity
)
=>
{
// 自定义
if
(
cur
.
flag
===
1
)
{
const
cusList
:
customizeEntity
[]
=
cur
.
productSpecList
&&
cur
.
productSpecList
.
reduce
((
preProd
:
any
,
curProd
:
customizeEntity
,
index
:
number
)
=>
{
const
obj
:
UploadFile
=
{
uid
:
`img
${
index
}
`
,
status
:
'done'
,
url
:
curProd
.
specImage
,
name
:
'image'
,
};
preProd
.
push
({
...
curProd
,
fileList
:
[
obj
]
});
return
preProd
;
},
[]);
cur
.
customizeInfo
=
cusList
;
}
else
{
const
specId
:
number
[]
=
result
.
directoryId
===
2
?
cur
.
industrySpecList
&&
cur
.
industrySpecList
.
map
((
curIndu
:
any
)
=>
{
return
{
mallSpecId
:
curIndu
.
industrySpecId
,
specName
:
curIndu
.
specName
,
partNo
:
curIndu
.
partNo
,
id
:
curIndu
.
id
,
};
})
:
cur
.
productSpecList
&&
cur
.
productSpecList
.
map
((
item
:
any
)
=>
{
return
{
mallSpecId
:
item
.
productSpec
,
specName
:
item
.
specName
,
partNo
:
item
.
partNo
,
id
:
item
.
id
,
};
});
cur
.
specIds
=
specId
;
}
pre
.
push
({
...
cur
,
productName
:
cur
.
skuName
});
return
pre
;
},
[]);
setGoodsSpecCopy
(
result
.
goodsSpec
);
setOtherService
(
result
.
otherService
.
map
((
v
)
=>
v
.
saleServiceId
));
setSpecData
(
specList
);
});
};
//保存
const
saveSubmit
=
()
=>
{
const
baseInfoForm
=
baseInfoRef
.
current
.
baseInform
;
baseInfoForm
.
validateFields
().
then
((
values
:
any
)
=>
{
if
(
specData
.
length
===
0
)
{
return
message
.
warning
(
'清添加库存规格'
);
}
//主图
values
.
images
=
[
{
imgType
:
0
,
imgUrl
:
values
.
mainImg
[
0
].
url
,
id
:
goodsDetail
?
goodsDetail
.
images
.
some
((
i
)
=>
i
.
id
===
values
.
mainImg
[
0
].
id
)
?
values
.
mainImg
[
0
].
id
:
undefined
:
undefined
,
},
];
//副图
if
(
values
.
subImg
)
{
values
.
images
.
push
(
...
values
.
subImg
.
map
((
v
:
any
)
=>
({
imgType
:
1
,
imgUrl
:
v
.
url
,
id
:
goodsDetail
?
goodsDetail
.
images
.
some
((
i
)
=>
i
.
id
===
v
.
id
)
?
v
.
id
:
undefined
:
undefined
,
})),
);
}
//分类
values
.
categoryByOne
=
values
.
masterTypeId
[
0
];
values
.
categoryByTwo
=
values
.
masterTypeId
[
1
]
||
undefined
;
// 过滤对象属性
const
goodsSpecVO
:
specEntity
[]
=
specData
.
reduce
((
pre
:
any
,
cur
:
specEntity
)
=>
{
cur
.
customizeInfo
=
cur
.
customizeInfo
?.
reduce
((
cusPre
:
any
,
cusCur
:
customizeEntity
)
=>
{
const
bol
:
boolean
=
goodsSpecCopy
.
some
((
i
:
specEntity
)
=>
{
return
i
.
customizeInfo
?.
some
((
i
:
customizeEntity
)
=>
i
.
id
===
cusCur
.
id
);
});
cusPre
=
[
...
cusPre
,
bol
?
filterObjAttr
(
cusCur
,
[
'fileList'
])
:
filterObjAttr
(
cusCur
,
[
'id'
,
'fileList'
]),
];
return
cusPre
;
},
[]);
// 存在对象属性改变!
cur
.
specIds
=
cur
.
specIds
?.
reduce
((
preSpec
:
any
,
curSpec
:
any
)
=>
{
preSpec
=
[...
preSpec
,
filterObjAttr
(
curSpec
,
[
'specName'
,
'partNo'
])];
return
preSpec
;
},
[]);
// 是否新增
const
isAdd
:
boolean
=
goodsSpecCopy
.
every
((
i
:
specEntity
)
=>
i
.
id
!=
cur
.
id
);
// 是否修改了某一条
const
isEdit
:
boolean
=
goodsSpecCopy
.
every
(
(
i
:
specEntity
)
=>
i
.
categoryId
!=
cur
.
categoryId
,
);
pre
=
[
...
pre
,
!
isAdd
?
isEdit
?
filterObjAttr
(
cur
,
[
'industrySpecList'
,
'productSpecList'
,
'skuName'
,
'id'
])
:
filterObjAttr
(
cur
,
[
'industrySpecList'
,
'productSpecList'
,
'skuName'
])
:
filterObjAttr
(
cur
,
[
'id'
,
'skuName'
]),
];
return
pre
;
},
[]);
goodsAPI
[
goodsDetail
?
'editGoods'
:
'addGoods'
]({
...
filterObjAttr
(
values
,
[
'mainImg'
,
'subImg'
,
'video'
,
'masterTypeId'
,
'id'
,
'goodsDesc'
]),
productSpec
:
goodsSpecVO
,
goodsType
:
0
,
goodsDetailVO
:
{
goodsDesc
:
values
.
goodsDesc
,
productDesc
:
productIntroduce
},
otherService
:
otherService
,
id
:
goodsDetail
?
goodsDetail
.
id
:
undefined
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
goodsDetail
?
'编辑成功'
:
'新增成功'
);
navigate
(
-
1
);
}
});
});
};
//返回
const
backRoute
=
()
=>
{
navigate
(
-
1
);
};
useEffect
(()
=>
{
if
(
searchParams
.
get
(
'id'
))
{
getGoodsDetail
(
Number
(
searchParams
.
get
(
'id'
)));
}
setIsDetail
(
!!
searchParams
.
get
(
'isDetail'
));
getSkuUnit
();
},
[]);
return
(
<
div
className=
'goods-info'
>
{
/* 基本信息*/
}
<
BaseInfo
ref=
{
baseInfoRef
}
categoryList=
{
categoryList
}
getCategoryList=
{
getCategoryList
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
goodsType=
{
0
}
/>
{
/* 库存规格*/
}
<
StockSku
addOrEditSku=
{
addOrEditSkuShowEvent
}
specData=
{
specData
}
skuUnitList=
{
skuUnitList
}
deleteSku=
{
deleteSkuEvent
}
isDetail=
{
isDetail
}
/>
{
/*其它信息*/
}
<
OtherInfo
otherServiceSelect=
{
otherServiceSelect
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
/>
{
/*产品介绍图*/
}
<
GoodsIntroduce
getRichText=
{
getRichText
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
/>
{
/*库存规格,添加、编辑弹窗*/
}
<
AddOrEditSkuModal
currentDesc=
{
currentDesc
}
open=
{
addOrEditSkuModalShow
}
handleCancel=
{
addOrEditSkuModalCancel
}
handleOk=
{
addOrEditSkuModalOk
}
skuUnitList=
{
skuUnitList
}
curtRowData=
{
curtRowData
}
goodsType=
{
0
}
/>
<
div
className=
'goods-info-operate'
>
{
!
isDetail
&&
(
<
Button
type=
'primary'
onClick=
{
saveSubmit
}
>
保存
</
Button
>
)
}
<
Button
onClick=
{
backRoute
}
>
返回
</
Button
>
</
div
>
</
div
>
);
};
export
default
GoodsAddOrEditOrDetail
;
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/index.scss
浏览文件 @
3018428e
.goods-info
{
&
-operate
{
margin-top
:
50px
;
display
:
flex
;
justify-content
:
center
;
button
{
width
:
100px
;
height
:
40px
;
&
:first-child
{
margin-right
:
50px
;
.goods-operate-wrap
{
position
:
relative
;
.next-step
{
margin
:
20px
0
0
0px
;
text-align
:
center
;
button
{
&
:first-child
{
margin-right
:
20px
;
}
width
:
100px
;
}
}
.back-btn
{
position
:
absolute
;
right
:
0
;
top
:
0
;
}
}
src/pages/mallManage/mallGoods/goodsAddOrEditOrDetail/index.tsx
浏览文件 @
3018428e
import
BaseInfo
from
'~/components/goods/commonAddOrEdit/baseInfo'
;
import
StockSku
from
'~/components/goods/commonAddOrEdit/stockSku'
;
import
OtherInfo
from
'~/components/goods/commonAddOrEdit/otherInfo'
;
import
GoodsIntroduce
from
'~/components/goods/commonAddOrEdit/goodsIntroduce'
;
import
AddOrEditSkuModal
from
'~/components/goods/commonAddOrEdit/addOrEditSkuModal'
;
import
{
Button
,
message
}
from
'antd'
;
import
{
useNavigate
,
useSearchParams
}
from
'react-router-dom'
;
import
'./index.scss'
;
import
{
Button
,
message
,
Tabs
,
TabsProps
}
from
'antd'
;
import
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
categoryListType
}
from
'~/api/interface/categoryManage'
;
import
{
customizeEntity
,
detailGoodsType
,
skuUnitType
,
specEntity
,
}
from
'~/api/interface/goodsType'
;
import
goodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
filterObjAttr
}
from
'~/utils'
;
import
BaseInfo
from
'./components/baseInfo'
;
import
SkuInfo
from
'./components/skuInfo'
;
import
IntroduceInfo
from
'./components/introduceInfo'
;
import
SkuAddOrEditModal
from
'./components/skuAddOrEditModal'
;
import
'./index.scss'
;
import
{
useNavigate
,
useSearchParams
}
from
'react-router-dom'
;
import
{
baseInfoType
}
from
'./components/baseInfo'
;
import
{
InterDataType
,
InterReqType
}
from
'~/api/interface'
;
import
{
addMallGoodsType
,
mallGoodsDetailsType
,
skuUnitType
}
from
'~/api/interface/goodsType'
;
import
GoodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
UploadFile
}
from
'antd/es/upload/interface
'
;
import
{
filterObjAttr
}
from
'~/utils
'
;
//
分类返回
类型
type
categoryType
=
InterDataType
<
categoryListType
>
[
'list'
];
//
产品-规格
单位返回类型
//
商品sku规格
类型
type
goodsSpecType
=
Exclude
<
InterReqType
<
addMallGoodsType
>
,
undefined
>
[
'goodsSpecList'
][
0
];
//单位返回类型
type
unitType
=
InterDataType
<
skuUnitType
>
;
//商品返回类型
type
goodsDetailType
=
InterDataType
<
detailGood
sType
>
;
//商品
详情-
返回类型
type
goodsDetailType
=
InterDataType
<
mallGoodsDetail
sType
>
;
const
GoodsAddOrEditOrDetail
=
()
=>
{
const
[
searchParams
]
=
useSearchParams
();
//基本信息ref
const
baseInfoRef
=
useRef
<
any
>
();
const
navigate
=
useNavigate
();
//当前目录
const
[
currentDesc
,
setCurrentDesc
]
=
useState
<
number
>
(
-
1
);
//分类
const
[
categoryList
,
setCategoryList
]
=
useState
<
categoryType
>
([]);
//添加、编辑库存规格弹窗
const
[
addOrEditSkuModalShow
,
setAddOrEditSkuModalShow
]
=
useState
(
false
);
//库存规格数据
const
[
specData
,
setSpecData
]
=
useState
<
specEntity
[]
>
([]);
const
[
goodsSpecCopy
,
setGoodsSpecCopy
]
=
useState
<
specEntity
[]
>
([]);
//产品规格-单位
const
[
searchParams
]
=
useSearchParams
();
//单位列表
const
[
skuUnitList
,
setSkuUnitList
]
=
useState
<
unitType
>
([]);
//其它服务
const
[
otherService
,
setOtherService
]
=
useState
<
number
[]
>
([]);
// 当前操作行数据
const
[
curtRowData
,
setCurtRowData
]
=
useState
<
Partial
<
specEntity
>>
({});
const
[
tabSelectKeys
,
setTabSelectKeys
]
=
useState
<
string
>
(
'1'
);
//新增、编辑sku弹窗
const
[
addOrEditSkuModalShow
,
setAddOrEditSkuModalShow
]
=
useState
<
boolean
>
(
false
);
//当前编辑sku
const
[
currentSku
,
setCurrentSku
]
=
useState
<
goodsSpecType
>
();
//skuTable数据
const
[
skuTable
,
setSkuTable
]
=
useState
<
goodsSpecType
[]
>
([]);
//商品介绍详情
const
[
goodsDetails
,
setGoodsDetails
]
=
useState
<
string
>
(
''
);
//商品id
const
[
goodsId
,
setGoodsId
]
=
useState
<
number
>
(
0
);
//商品详情
const
[
goodsDetail
,
setGoodsDetail
]
=
useState
<
goodsDetailType
>
();
//产品介绍
const
[
productIntroduce
,
setProductIntroduce
]
=
useState
<
string
>
(
''
);
//是否商品详情
const
[
isDetail
,
setIsDetail
]
=
useState
<
boolean
>
(
false
);
const
[
goodsDetailsInfo
,
setGoodsDetailsInfo
]
=
useState
<
goodsDetailType
>
();
//添加、编辑规格
const
addOrEditSkuShowEvent
=
(
record
?:
specEntity
)
=>
{
const
baseInfoForm
=
baseInfoRef
.
current
.
baseInform
;
setCurrentDesc
(
baseInfoForm
.
getFieldValue
(
'directoryId'
)
||
-
1
);
if
(
!
baseInfoForm
.
getFieldValue
(
'directoryId'
))
{
return
message
.
warning
(
'请先选择目录'
);
}
if
(
record
)
{
setCurtRowData
({
...
record
});
}
//新增、编辑sku弹窗显示
const
addOrEditSkuClick
=
(
record
?:
goodsSpecType
)
=>
{
setCurrentSku
(
record
?
{
...
record
}
:
undefined
);
setAddOrEditSkuModalShow
(
true
);
};
//删除规格
const
deleteSkuEvent
=
(
record
:
specEntity
)
=>
{
const
index
=
specData
.
findIndex
((
v
)
=>
v
.
id
===
record
.
id
);
specData
.
splice
(
index
,
1
);
setSpecData
([...
specData
]);
};
const
addOrEditSkuModalCancel
=
()
=>
{
setAddOrEditSkuModalShow
(
false
);
setCurtRowData
({});
};
const
addOrEditSkuModalOk
=
(
data
:
specEntity
)
=>
{
if
(
Object
.
keys
(
curtRowData
).
length
!=
0
)
{
const
index
:
number
=
specData
.
findIndex
((
i
)
=>
i
.
id
===
data
.
id
);
specData
.
splice
(
index
,
1
,
data
);
setSpecData
([...
specData
]);
const
addOrEditSkuModalOk
=
(
values
:
goodsSpecType
)
=>
{
setAddOrEditSkuModalShow
(
false
);
const
skuTableIndex
:
number
=
skuTable
.
findIndex
((
v
)
=>
v
.
id
===
values
.
id
);
if
(
skuTableIndex
!==
-
1
)
{
skuTable
.
splice
(
skuTableIndex
,
1
,
values
);
setSkuTable
([...
skuTable
]);
}
else
{
setS
pecData
([...
specData
,
data
]);
setS
kuTable
([...
skuTable
,
{
...
values
}
]);
}
addOrEditSkuModalCancel
();
};
//根据目录获取分类列表
const
getCategoryList
=
(
directoryId
:
number
)
=>
{
CategoryManageAPI
.
getCategoryList
({
directoryId
,
type
:
4
,
pageSize
:
9999
,
pageNo
:
1
}).
then
(
({
result
})
=>
{
setCategoryList
(
result
.
list
||
[]);
},
);
//sku删除
const
deleteSkuClick
=
(
record
:
goodsSpecType
)
=>
{
const
skuIndex
:
number
=
skuTable
.
findIndex
((
v
)
=>
v
.
id
===
record
.
id
);
skuTable
.
splice
(
skuIndex
,
1
);
setSkuTable
([...
skuTable
]);
};
//产品-单位
const
getSkuUnit
=
()
=>
{
goodsAPI
.
getSkuUnit
().
then
(({
result
})
=>
{
setSkuUnitList
(
result
||
[]);
});
};
//其它服务选择
const
otherServiceSelect
=
(
ids
:
number
[])
=>
{
setOtherService
(
ids
);
//商品详情获取
const
getIntroduceInfo
=
(
richText
:
string
)
=>
{
setGoodsDetails
(
richText
);
};
//获取产品详情
const
getRichText
=
(
html
?:
string
)
=>
{
setProductIntroduce
(
html
||
''
);
const
tabItems
:
TabsProps
[
'items'
]
=
[
{
key
:
'1'
,
label
:
`基础信息`
,
children
:
<
BaseInfo
ref=
{
baseInfoRef
}
/>,
},
{
key
:
'2'
,
label
:
`商品规格`
,
children
:
(
<
SkuInfo
addOrEditSkuClick=
{
addOrEditSkuClick
}
skuTableData=
{
skuTable
}
skuUnitList=
{
skuUnitList
}
deleteSkuClick=
{
deleteSkuClick
}
editSkuClick=
{
addOrEditSkuClick
}
/>
),
},
{
key
:
'3'
,
label
:
`商品详情`
,
children
:
<
IntroduceInfo
onChange=
{
getIntroduceInfo
}
introduceInfo=
{
goodsDetails
}
/>,
},
];
//tab 切换
const
tabSelectChange
=
(
key
:
string
)
=>
{
setTabSelectKeys
(
key
);
};
//商品详情
const
getGoodsDetail
=
(
goodsInfoId
:
number
)
=>
{
GoodsAPI
.
getGoodsDetail
({
goodsInfoId
,
type
:
0
}).
then
(({
result
})
=>
{
setGoodsDetail
(
result
);
getCategoryList
(
result
.
directoryId
);
const
specList
:
specEntity
[]
=
result
.
goodsSpec
.
reduce
((
pre
:
any
,
cur
:
specEntity
)
=>
{
// 自定义
if
(
cur
.
flag
===
1
)
{
const
cusList
:
customizeEntity
[]
=
cur
.
productSpecList
&&
cur
.
productSpecList
.
reduce
((
preProd
:
any
,
curProd
:
customizeEntity
,
index
:
number
)
=>
{
const
obj
:
UploadFile
=
{
uid
:
`img
${
index
}
`
,
status
:
'done'
,
url
:
curProd
.
specImage
,
name
:
'image'
,
};
preProd
.
push
({
...
curProd
,
fileList
:
[
obj
]
});
return
preProd
;
},
[]);
cur
.
customizeInfo
=
cusList
;
//下一步
const
toNextStep
=
()
=>
{
switch
(
tabSelectKeys
)
{
case
'1'
:
baseInfoRef
.
current
.
getForm
()
.
validateFields
()
.
then
(()
=>
{
setTabSelectKeys
((
Number
(
tabSelectKeys
)
+
1
).
toString
());
})
.
catch
((
error
:
any
)
=>
{
message
.
error
(
error
.
errorFields
[
0
].
errors
[
0
]);
});
break
;
case
'2'
:
if
(
skuTable
.
length
)
{
setTabSelectKeys
((
Number
(
tabSelectKeys
)
+
1
).
toString
());
}
else
{
const
specId
:
number
[]
=
result
.
directoryId
===
2
?
cur
.
industrySpecList
&&
cur
.
industrySpecList
.
map
((
curIndu
:
any
)
=>
{
return
{
mallSpecId
:
curIndu
.
industrySpecId
,
specName
:
curIndu
.
specName
,
partNo
:
curIndu
.
partNo
,
id
:
curIndu
.
id
,
};
})
:
cur
.
productSpecList
&&
cur
.
productSpecList
.
map
((
item
:
any
)
=>
{
return
{
mallSpecId
:
item
.
productSpec
,
specName
:
item
.
specName
,
partNo
:
item
.
partNo
,
id
:
item
.
id
,
};
});
cur
.
specIds
=
specId
;
message
.
warning
(
'请添加规格'
);
}
pre
.
push
({
...
cur
,
productName
:
cur
.
skuName
});
return
pre
;
},
[]);
setGoodsSpecCopy
(
result
.
goodsSpec
);
setOtherService
(
result
.
otherService
.
map
((
v
)
=>
v
.
saleServiceId
));
setSpecData
(
specList
);
break
;
case
'3'
:
break
;
default
:
break
;
}
};
//上一步
const
toBackStep
=
()
=>
{
setTabSelectKeys
((
Number
(
tabSelectKeys
)
-
1
).
toString
());
};
const
backRoute
=
()
=>
{
navigate
(
-
1
);
};
//单位列表
const
getSkuUnit
=
()
=>
{
GoodsAPI
.
getSkuUnit
().
then
(({
result
})
=>
{
setSkuUnitList
(
result
||
[]);
});
};
//保存
const
saveSubmit
=
()
=>
{
const
baseInfoForm
=
baseInfoRef
.
current
.
baseInform
;
baseInfoForm
.
validateFields
().
then
((
values
:
any
)
=>
{
if
(
specData
.
length
===
0
)
{
return
message
.
warning
(
'清添加库存规格'
);
}
//主图
values
.
images
=
[
{
imgType
:
0
,
imgUrl
:
values
.
mainImg
[
0
].
url
,
id
:
goodsDetail
?
goodsDetail
.
images
.
some
((
i
)
=>
i
.
id
===
values
.
mainImg
[
0
].
id
)
?
values
.
mainImg
[
0
].
id
:
undefined
:
undefined
,
},
];
//副图
if
(
values
.
subImg
)
{
values
.
images
.
push
(
...
values
.
subImg
.
map
((
v
:
any
)
=>
({
imgType
:
1
,
imgUrl
:
v
.
url
,
id
:
goodsDetail
?
goodsDetail
.
images
.
some
((
i
)
=>
i
.
id
===
v
.
id
)
?
v
.
id
:
undefined
//商品保存
const
saveGoods
=
()
=>
{
baseInfoRef
.
current
.
getForm
()
.
validateFields
()
.
then
((
values
:
baseInfoType
)
=>
{
if
(
skuTable
.
length
)
{
const
skuList
=
skuTable
.
map
((
v
)
=>
({
...
v
,
id
:
goodsDetailsInfo
?
goodsDetailsInfo
.
goodsSpecList
.
find
((
i
)
=>
i
.
id
===
v
.
id
)?.
id
:
undefined
,
})),
);
}
//分类
values
.
categoryByOne
=
values
.
masterTypeId
[
0
];
values
.
categoryByTwo
=
values
.
masterTypeId
[
1
]
||
undefined
;
// 过滤对象属性
const
goodsSpecVO
:
specEntity
[]
=
specData
.
reduce
((
pre
:
any
,
cur
:
specEntity
)
=>
{
cur
.
customizeInfo
=
cur
.
customizeInfo
?.
reduce
((
cusPre
:
any
,
cusCur
:
customizeEntity
)
=>
{
const
bol
:
boolean
=
goodsSpecCopy
.
some
((
i
:
specEntity
)
=>
{
return
i
.
customizeInfo
?.
some
((
i
:
customizeEntity
)
=>
i
.
id
===
cusCur
.
id
);
goodsSpecValuesList
:
v
.
goodsSpecValuesList
.
map
((
i
)
=>
({
...
i
,
id
:
goodsDetailsInfo
?
goodsDetailsInfo
.
goodsSpecList
.
find
((
j
)
=>
j
.
id
===
v
.
id
)
?.
goodsSpecValuesList
.
find
((
k
)
=>
k
.
id
===
i
.
id
)?.
id
:
undefined
,
goodsSpecId
:
goodsDetailsInfo
?
goodsDetailsInfo
.
goodsSpecList
.
find
((
i
)
=>
i
.
id
===
v
.
id
)?.
id
:
undefined
,
})),
}));
const
addGoodsEditReq
=
{
...
filterObjAttr
(
values
,
[
'mainImgList'
,
'subImgList'
,
'videoList'
,
'categoryId'
]),
resourcesList
:
[
...
values
.
mainImgList
.
map
((
v
)
=>
({
type
:
0
,
url
:
v
.
url
})),
...(
values
.
subImgList
?.
map
((
v
)
=>
({
type
:
1
,
url
:
v
.
url
}))
||
[]),
...(
values
.
videoList
?.
map
((
v
)
=>
({
type
:
2
,
url
:
v
.
url
}))
||
[]),
],
categoryPrimaryId
:
values
.
categoryId
[
0
],
categorySubId
:
values
.
categoryId
.
length
===
2
?
values
.
categoryId
[
1
]
:
undefined
,
goodsDetails
,
goodsSpecList
:
skuList
,
id
:
goodsId
||
undefined
,
};
GoodsAPI
[
goodsId
?
'editMallGoods'
:
'addMallGoods'
](
addGoodsEditReq
).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
goodsId
?
'编辑商城成功'
:
'新增商品成功'
);
navigate
(
-
1
);
}
});
cusPre
=
[
...
cusPre
,
bol
?
filterObjAttr
(
cusCur
,
[
'fileList'
])
:
filterObjAttr
(
cusCur
,
[
'id'
,
'fileList'
]),
];
return
cusPre
;
},
[]);
// 存在对象属性改变!
cur
.
specIds
=
cur
.
specIds
?.
reduce
((
preSpec
:
any
,
curSpec
:
any
)
=>
{
preSpec
=
[...
preSpec
,
filterObjAttr
(
curSpec
,
[
'specName'
,
'partNo'
])];
return
preSpec
;
},
[]);
// 是否新增
const
isAdd
:
boolean
=
goodsSpecCopy
.
every
((
i
:
specEntity
)
=>
i
.
id
!=
cur
.
id
);
// 是否修改了某一条
const
isEdit
:
boolean
=
goodsSpecCopy
.
every
(
(
i
:
specEntity
)
=>
i
.
categoryId
!=
cur
.
categoryId
,
);
pre
=
[
...
pre
,
!
isAdd
?
isEdit
?
filterObjAttr
(
cur
,
[
'industrySpecList'
,
'productSpecList'
,
'skuName'
,
'id'
])
:
filterObjAttr
(
cur
,
[
'industrySpecList'
,
'productSpecList'
,
'skuName'
])
:
filterObjAttr
(
cur
,
[
'id'
,
'skuName'
]),
];
return
pre
;
},
[]);
goodsAPI
[
goodsDetail
?
'editGoods'
:
'addGoods'
]({
...
filterObjAttr
(
values
,
[
'mainImg'
,
'subImg'
,
'video'
,
'masterTypeId'
,
'id'
,
'goodsDesc'
]),
productSpec
:
goodsSpecVO
,
goodsType
:
0
,
goodsDetailVO
:
{
goodsDesc
:
values
.
goodsDesc
,
productDesc
:
productIntroduce
},
otherService
:
otherService
,
id
:
goodsDetail
?
goodsDetail
.
id
:
undefined
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
goodsDetail
?
'编辑成功'
:
'新增成功'
);
navigate
(
-
1
);
}
else
{
message
.
warning
(
'商品规格未添加'
);
}
})
.
catch
((
error
:
any
)
=>
{
message
.
error
(
error
.
errorFields
[
0
].
errors
[
0
]);
});
});
};
//返回
const
backRoute
=
()
=>
{
navigate
(
-
1
);
//商品详情
const
getMallGoodsDetails
=
(
id
:
number
)
=>
{
GoodsAPI
.
getMallGoodsDetails
({
id
}).
then
(({
result
})
=>
{
const
mainImgList
=
result
.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
0
)
.
map
((
v
)
=>
({
id
:
v
.
id
,
name
:
'mainImg'
,
uid
:
v
.
id
,
url
:
v
.
url
}));
const
subImgList
=
result
.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
1
)
.
map
((
v
)
=>
({
id
:
v
.
id
,
name
:
'subImg'
,
uid
:
v
.
id
,
url
:
v
.
url
}));
const
videoList
=
result
.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
2
)
.
map
((
v
)
=>
({
id
:
v
.
id
,
name
:
'video'
,
uid
:
v
.
id
,
url
:
v
.
url
}));
setGoodsDetailsInfo
(
JSON
.
parse
(
JSON
.
stringify
(
result
)));
setSkuTable
(
result
.
goodsSpecList
);
setGoodsDetails
(
result
.
goodsDetails
||
''
);
baseInfoRef
.
current
.
getForm
().
setFieldsValue
({
tradeName
:
result
.
tradeName
,
description
:
result
.
description
||
undefined
,
mainImgList
,
subImgList
:
subImgList
.
length
?
subImgList
:
undefined
,
videoList
:
videoList
.
length
?
videoList
:
undefined
,
categoryId
:
result
.
categorySubId
?
[
result
.
categoryPrimaryId
,
result
.
categorySubId
]
:
[
result
.
categoryPrimaryId
],
shelfStatus
:
result
.
shelfStatus
,
labelShow
:
result
.
labelShow
,
goodsLabel
:
result
.
goodsLabel
||
undefined
,
});
baseInfoRef
.
current
.
setLabelShow
(
!!
result
.
labelShow
);
baseInfoRef
.
current
.
mediaData
.
setMainFileList
(
mainImgList
);
baseInfoRef
.
current
.
mediaData
.
setSubFileList
(
subImgList
);
baseInfoRef
.
current
.
mediaData
.
setVideoFileList
(
videoList
);
});
};
useEffect
(()
=>
{
getSkuUnit
();
if
(
searchParams
.
get
(
'id'
))
{
getGoodsDetail
(
Number
(
searchParams
.
get
(
'id'
)));
setGoodsId
(
Number
(
searchParams
.
get
(
'id'
)));
getMallGoodsDetails
(
Number
(
searchParams
.
get
(
'id'
)));
}
setIsDetail
(
!!
searchParams
.
get
(
'isDetail'
));
getSkuUnit
();
},
[]);
return
(
<
div
className=
'goods-info'
>
{
/* 基本信息*/
}
<
BaseInfo
ref=
{
baseInfoRef
}
categoryList=
{
categoryList
}
getCategoryList=
{
getCategoryList
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
goodsType=
{
0
}
/>
{
/* 库存规格*/
}
<
StockSku
addOrEditSku=
{
addOrEditSkuShowEvent
}
specData=
{
specData
}
skuUnitList=
{
skuUnitList
}
deleteSku=
{
deleteSkuEvent
}
isDetail=
{
isDetail
}
/>
{
/*其它信息*/
}
<
OtherInfo
otherServiceSelect=
{
otherServiceSelect
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
/>
{
/*产品介绍图*/
}
<
GoodsIntroduce
getRichText=
{
getRichText
}
goodsDetail=
{
goodsDetail
}
isDetail=
{
isDetail
}
/>
{
/*库存规格,添加、编辑弹窗*/
}
<
AddOrEditSkuModal
currentDesc=
{
currentDesc
}
open=
{
addOrEditSkuModalShow
}
handleCancel=
{
addOrEditSkuModalCancel
}
handleOk=
{
addOrEditSkuModalOk
}
skuUnitList=
{
skuUnitList
}
curtRowData=
{
curtRowData
}
goodsType=
{
0
}
/>
<
div
className=
'goods-info-operate'
>
{
!
isDetail
&&
(
<
Button
type=
'primary'
onClick=
{
saveSubmit
}
>
保存
<
div
className=
'goods-operate-wrap'
>
<
Tabs
items=
{
tabItems
}
activeKey=
{
tabSelectKeys
}
onChange=
{
tabSelectChange
}
></
Tabs
>
<
div
className=
'next-step'
>
{
tabSelectKeys
!==
'1'
?
<
Button
onClick=
{
toBackStep
}
>
上一步
</
Button
>
:
''
}
{
tabSelectKeys
!==
'3'
?
(
<
Button
type=
'primary'
onClick=
{
toNextStep
}
>
下一步
</
Button
>
)
:
(
''
)
}
<
Button
onClick=
{
backRoute
}
>
返回
</
Button
>
</
div
>
<
div
className=
'back-btn'
>
<
Button
type=
'primary'
onClick=
{
saveGoods
}
style=
{
{
marginRight
:
'10px'
}
}
>
保存
</
Button
>
<
Button
type=
'default'
onClick=
{
backRoute
}
>
返回
</
Button
>
</
div
>
{
/*新增、编辑sku弹窗*/
}
<
SkuAddOrEditModal
open=
{
addOrEditSkuModalShow
}
onCancel=
{
addOrEditSkuModalCancel
}
onHandleOk=
{
addOrEditSkuModalOk
}
skuUnitList=
{
skuUnitList
}
currentSku=
{
currentSku
}
/>
</
div
>
);
};
...
...
src/pages/mallManage/mallGoods/goodsDetails/index.scss
0 → 100644
浏览文件 @
3018428e
.goods-detail
{
position
:
relative
;
&
-info
{
margin-bottom
:
20px
;
}
&
-sku
{
.sku-title
{
line-height
:
50px
;
font-weight
:
bold
;
font-size
:
14px
;
}
}
&
-introduce
{
.introduce-title
{
line-height
:
50px
;
font-weight
:
bold
;
font-size
:
14px
;
}
}
&
-operate
{
position
:
absolute
;
right
:
0
;
top
:
0
;
}
}
src/pages/mallManage/mallGoods/goodsDetails/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
useSearchParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
useEffect
,
useState
}
from
'react'
;
import
GoodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
mallGoodsDetailsType
,
skuUnitType
}
from
'~/api/interface/goodsType'
;
import
{
Badge
,
Button
,
Descriptions
,
Image
,
Table
,
Tag
}
from
'antd'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
{
categoryListRespType
}
from
'~/api/interface/categoryManage'
;
import
'./index.scss'
;
import
{
ColumnsType
}
from
'antd/es/table'
;
//详情返回类型
type
detailType
=
InterDataType
<
mallGoodsDetailsType
>
;
//分类返回类型
type
categoryType
=
InterDataType
<
categoryListRespType
>
[
'list'
];
//单位返回类型
type
unitType
=
InterDataType
<
skuUnitType
>
;
const
GoodsDetails
=
()
=>
{
const
[
searchParams
]
=
useSearchParams
();
const
navigate
=
useNavigate
();
//分类列表
const
[
categoryList
,
setCategoryList
]
=
useState
<
categoryType
>
([]);
//单位列表
const
[
skuUnitList
,
setSkuUnitList
]
=
useState
<
unitType
>
([]);
const
[
goodsInfoDetails
,
setGoodsInfoDetails
]
=
useState
<
detailType
>
();
const
tableColumns
:
ColumnsType
<
detailType
[
'goodsSpecList'
][
0
]
>
=
[
{
title
:
'序号'
,
align
:
'center'
,
render
:
(
_text
:
string
,
_record
,
index
:
number
)
=>
index
+
1
,
},
{
title
:
'规格名称'
,
align
:
'center'
,
dataIndex
:
'specName'
,
},
{
title
:
'选择方式'
,
align
:
'center'
,
dataIndex
:
'chooseType'
,
render
:
(
text
:
number
)
=>
(
text
?
'多选'
:
'单选'
),
},
{
title
:
'是否必选'
,
align
:
'center'
,
dataIndex
:
'must'
,
render
:
(
text
:
number
)
=>
(
text
?
'必选'
:
'非必选'
),
},
{
title
:
'规格单位'
,
align
:
'center'
,
dataIndex
:
'skuUnitId'
,
render
:
(
text
:
number
)
=>
skuUnitList
.
find
((
v
)
=>
v
.
id
===
text
)?.
unitName
||
''
,
},
{
title
:
'规格值'
,
align
:
'center'
,
dataIndex
:
'goodsSpecValuesList'
,
render
:
(
text
:
detailType
[
'goodsSpecList'
][
0
][
'goodsSpecValuesList'
])
=>
text
.
map
((
v
)
=>
(
<
Tag
key=
{
v
.
id
}
>
{
v
.
specValueName
}
{
v
.
partNo
?
`(${v.partNo})`
:
''
}
</
Tag
>
)),
},
];
const
getGoodsDetails
=
(
id
:
number
)
=>
{
GoodsAPI
.
getMallGoodsDetails
({
id
}).
then
(({
result
})
=>
{
setGoodsInfoDetails
(
result
);
});
};
//分类列表
const
getCategoryList
=
()
=>
{
CategoryManageAPI
.
getCategoryRespList
({
pageNo
:
1
,
pageSize
:
99999
}).
then
(({
result
})
=>
{
setCategoryList
(
result
.
list
||
[]);
});
};
//单位列表
const
getSkuUnit
=
()
=>
{
GoodsAPI
.
getSkuUnit
().
then
(({
result
})
=>
{
setSkuUnitList
(
result
||
[]);
});
};
//返回
const
backRoute
=
()
=>
{
navigate
(
-
1
);
};
useEffect
(()
=>
{
getGoodsDetails
(
Number
(
searchParams
.
get
(
'id'
)));
getCategoryList
();
getSkuUnit
();
},
[]);
return
(
<
div
className=
'goods-detail'
>
<
div
className=
'goods-detail-info'
>
<
Descriptions
title=
'基本信息'
bordered
>
<
Descriptions
.
Item
label=
'商品名称'
>
{
goodsInfoDetails
?.
tradeName
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品副图'
>
{
goodsInfoDetails
?.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
1
)
.
map
((
v
)
=>
(
<
Image
src=
{
v
.
url
}
width=
{
50
}
height=
{
50
}
key=
{
v
.
id
}
/>
))
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品主图'
>
{
goodsInfoDetails
?.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
0
)
.
map
((
v
)
=>
(
<
Image
src=
{
v
.
url
}
width=
{
50
}
height=
{
50
}
key=
{
v
.
id
}
/>
))
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品标签'
>
{
goodsInfoDetails
?.
goodsLabel
||
'暂无'
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品分类'
>
{
categoryList
.
reduce
((
pre
:
string
[],
cur
)
=>
{
if
(
cur
.
id
===
goodsInfoDetails
?.
categoryPrimaryId
)
{
pre
.
push
(
cur
.
name
);
if
(
goodsInfoDetails
?.
categorySubId
)
{
pre
.
push
(
cur
.
subDTOList
.
find
((
v
)
=>
v
.
id
===
goodsInfoDetails
?.
categorySubId
)?.
name
||
''
,
);
}
}
return
pre
;
},
[])
.
join
(
'/'
)
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品状态'
>
<
Badge
status=
{
goodsInfoDetails
?.
shelfStatus
?
'processing'
:
'default'
}
text=
{
goodsInfoDetails
?.
shelfStatus
?
'上架中'
:
'已下架'
}
/>
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品视频'
span=
{
1
}
>
{
goodsInfoDetails
?.
resourcesList
.
filter
((
v
)
=>
v
.
type
===
2
)
.
map
((
v
)
=>
(
<
video
src=
{
v
.
url
}
key=
{
v
.
id
}
style=
{
{
width
:
'200px'
,
height
:
'200px'
}
}
controls
/>
))
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'商品描述'
>
{
goodsInfoDetails
?.
description
}
</
Descriptions
.
Item
>
</
Descriptions
>
</
div
>
<
div
className=
'goods-detail-sku'
>
<
div
className=
'sku-title'
>
商品规格
</
div
>
<
Table
bordered
columns=
{
tableColumns
}
dataSource=
{
goodsInfoDetails
?.
goodsSpecList
}
rowKey=
'id'
pagination=
{
false
}
></
Table
>
</
div
>
<
div
className=
'goods-detail-introduce'
>
<
div
className=
'introduce-title'
>
商品详情
</
div
>
<
div
className=
'introduce-content'
dangerouslySetInnerHTML=
{
{
__html
:
goodsInfoDetails
?.
goodsDetails
||
''
}
}
></
div
>
</
div
>
<
div
className=
'goods-detail-operate'
>
<
Button
type=
'primary'
onClick=
{
backRoute
}
>
返回
</
Button
>
</
div
>
</
div
>
);
};
export
default
GoodsDetails
;
src/pages/mallManage/mallGoods/goodsList/index.tsx
浏览文件 @
3018428e
...
...
@@ -2,30 +2,32 @@ import SearchBox, { searchColumns } from '~/components/search-box';
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
{
useNavigate
,
useSearchParams
}
from
'react-router-dom'
;
import
{
Button
,
Card
,
Image
,
message
,
Modal
,
Table
}
from
'antd'
;
import
{
ArrowDownOutlined
,
ArrowUpOutlined
,
DeleteOutlined
,
PlusOutlined
,
}
from
'@ant-design/icons'
;
import
{
ArrowDownOutlined
,
ArrowUpOutlined
,
PlusOutlined
}
from
'@ant-design/icons'
;
import
{
ColumnsType
}
from
'antd/es/table'
;
import
GoodsAPI
from
'~/api/modules/goodsAPI'
;
import
{
InterDataType
,
InterReqType
,
PaginationProps
}
from
'~/api/interface'
;
import
{
listGoodsType
}
from
'~/api/interface/goodsType'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
{
listPageGoodsInfoType
}
from
'~/api/interface/goodsType'
;
import
{
filterObjAttr
}
from
'~/utils'
;
import
qs
from
'query-string'
;
import
{
CategoryManageAPI
}
from
'~/api'
;
import
{
categoryListRespType
}
from
'~/api/interface/categoryManage'
;
import
{
useSelector
}
from
'react-redux'
;
import
_
from
'lodash'
;
//商品返回类型
type
goodsType
=
InterDataType
<
list
Goods
Type
>
[
'list'
];
type
goodsType
=
InterDataType
<
list
PageGoodsInfo
Type
>
[
'list'
];
//商品列表筛选类型
type
goodsSearchParameters
=
Omit
<
InterReqType
<
listGoodsType
>
,
'goodsType'
>
;
type
goodsSearchParameters
=
InterReqType
<
listPageGoodsInfoType
>
;
//分类返回类型
type
categoryType
=
InterDataType
<
categoryListRespType
>
[
'list'
];
const
GoodsList
=
()
=>
{
//筛选ref
const
searchRef
=
useRef
();
const
navigate
=
useNavigate
();
const
[
searchParams
,
setSearchParams
]
=
useSearchParams
();
const
{
userInfo
}
=
useSelector
((
state
:
any
)
=>
state
.
UserInfo
);
const
tabList
=
[
{
key
:
'1'
,
...
...
@@ -41,26 +43,22 @@ const GoodsList = () => {
},
];
const
[
activeTabKey
,
setActiveTabKey
]
=
useState
<
string
>
(
'1'
);
//分类列表
const
[
categoryList
,
setCategoryList
]
=
useState
<
categoryType
>
([]);
const
[
searchColumns
,
setSearchColumns
]
=
useState
<
searchColumns
[]
>
([
{
label
:
'商品名称'
,
placeholder
:
'请输入商品名称'
,
name
:
'
goods
Name'
,
name
:
'
trade
Name'
,
type
:
'input'
,
},
{
label
:
'
所属目录
'
,
placeholder
:
'请选择
所属目录
'
,
name
:
'
directo
ryId'
,
label
:
'
商品类型
'
,
placeholder
:
'请选择
商品类别
'
,
name
:
'
categoryPrima
ryId'
,
type
:
'select'
,
options
:
[],
},
{
label
:
'创建时间'
,
placeholder
:
'请输入选择创建时间'
,
name
:
'time'
,
type
:
'rangePicker'
,
},
]);
const
tableColumns
:
ColumnsType
<
goodsType
[
0
]
>
=
[
{
...
...
@@ -72,23 +70,30 @@ const GoodsList = () => {
{
title
:
'图片'
,
align
:
'center'
,
dataIndex
:
'imgUrl'
,
render
:
(
text
:
string
)
=>
<
Image
src=
{
text
}
width=
{
50
}
height=
{
50
}
/>,
dataIndex
:
'resourcesList'
,
render
:
(
text
:
goodsType
[
0
][
'resourcesList'
])
=>
(
<
Image
src=
{
text
.
find
((
v
)
=>
v
.
type
===
0
)?.
url
||
''
}
width=
{
50
}
height=
{
50
}
/>
),
},
{
title
:
'商品名称'
,
align
:
'center'
,
dataIndex
:
'tradeName'
,
width
:
'20%'
,
ellipsis
:
true
},
{
title
:
'商品类别'
,
align
:
'center'
,
render
:
(
_text
:
string
,
record
:
goodsType
[
0
])
=>
getCategoryStr
(
record
),
},
{
title
:
'商品名称'
,
align
:
'center'
,
dataIndex
:
'goodsName'
},
{
title
:
'所属目录'
,
align
:
'center'
,
dataIndex
:
'directoryName'
},
{
title
:
'创建时间'
,
align
:
'center'
,
dataIndex
:
'createTime'
},
{
title
:
'状态'
,
align
:
'center'
,
dataIndex
:
'status'
,
dataIndex
:
's
helfS
tatus'
,
render
:
(
text
:
number
)
=>
(
text
?
'上架'
:
'下架'
),
},
{
title
:
'操作'
,
align
:
'center'
,
dataIndex
:
'id'
,
render
:
(
id
:
number
)
=>
(
width
:
'20%'
,
render
:
(
id
:
number
,
record
:
goodsType
[
0
])
=>
(
<>
<
Button
type=
'link'
onClick=
{
()
=>
toEditGoods
(
id
)
}
>
编辑
...
...
@@ -96,6 +101,15 @@ const GoodsList = () => {
<
Button
type=
'link'
onClick=
{
()
=>
toGoodsDetail
(
id
)
}
>
详情
</
Button
>
<
Button
type=
'link'
onClick=
{
()
=>
upOrDownShelf
(
1
,
id
)
}
disabled=
{
!!
record
.
shelfStatus
}
>
上架
</
Button
>
<
Button
type=
'link'
onClick=
{
()
=>
upOrDownShelf
(
0
,
id
)
}
disabled=
{
!
record
.
shelfStatus
}
>
下架
</
Button
>
<
Button
type=
'link'
danger
onClick=
{
()
=>
removeMallGoods
(
id
)
}
>
删除
</
Button
>
</>
),
},
...
...
@@ -113,20 +127,20 @@ const GoodsList = () => {
totalPage
:
1
,
});
//筛选
const
[
query
,
setQuery
]
=
useState
<
goodsSearchParameters
>
({
status
:
undefined
});
const
[
query
,
setQuery
]
=
useState
<
goodsSearchParameters
>
({
s
helfS
tatus
:
undefined
});
// 表格多选
const
[
selectedRowKeys
,
setSelectedRowKeys
]
=
useState
<
React
.
Key
[]
>
([]);
const
onTabChange
=
(
key
:
string
)
=>
{
pagination
.
pageNo
=
1
;
pagination
.
pageSize
=
10
;
query
.
status
=
key
===
'1'
?
undefined
:
key
===
'2'
?
1
:
0
;
query
.
s
helfS
tatus
=
key
===
'1'
?
undefined
:
key
===
'2'
?
1
:
0
;
setSearchParams
(
qs
.
stringify
({
pageNo
:
1
,
pageSize
:
10
,
...
query
,
s
tatus
:
query
.
status
===
undefined
?
'all'
:
query
.
s
tatus
,
s
helfStatus
:
query
.
shelfStatus
===
undefined
?
'all'
:
query
.
shelfS
tatus
,
}),
);
getGoodsList
(
query
);
...
...
@@ -137,12 +151,13 @@ const GoodsList = () => {
const
paginationChange
=
(
pageNo
:
number
,
pageSize
:
number
)
=>
{
pagination
.
pageNo
=
pageNo
;
pagination
.
pageSize
=
pageSize
;
setSelectedRowKeys
([]);
setSearchParams
(
qs
.
stringify
({
pageNo
:
pageNo
,
pageSize
:
pageSize
,
...
query
,
s
tatus
:
query
.
status
===
undefined
?
'all'
:
query
.
s
tatus
,
s
helfStatus
:
query
.
shelfStatus
===
undefined
?
'all'
:
query
.
shelfS
tatus
,
}),
);
getGoodsList
(
query
);
...
...
@@ -152,28 +167,24 @@ const GoodsList = () => {
const
searchSuccess
=
(
data
:
any
)
=>
{
pagination
.
pageNo
=
1
;
pagination
.
pageSize
=
10
;
setQuery
({
...
filterObjAttr
(
data
,
[
'time'
]),
status
:
query
.
status
});
getGoodsList
({
...
filterObjAttr
(
data
,
[
'time'
]),
status
:
query
.
status
});
getGoodsList
(
{
...
filterObjAttr
(
data
,
[
'time'
]),
status
:
query
.
status
,
pageSize
:
9999
,
pageNo
:
1
},
true
,
);
setQuery
({
...
data
,
shelfStatus
:
query
.
shelfStatus
});
getGoodsList
({
...
data
,
shelfStatus
:
query
.
shelfStatus
});
getGoodsList
({
...
data
,
shelfStatus
:
query
.
shelfStatus
,
pageSize
:
9999
,
pageNo
:
1
},
true
);
setSearchParams
(
qs
.
stringify
({
pageNo
:
1
,
pageSize
:
10
,
...
filterObjAttr
(
data
,
[
'time'
]),
s
tatus
:
query
.
status
===
undefined
?
'all'
:
query
.
s
tatus
,
s
helfStatus
:
query
.
shelfStatus
===
undefined
?
'all'
:
query
.
shelfS
tatus
,
}),
);
};
//商品列表
const
getGoodsList
=
(
query
?:
goodsSearchParameters
,
isAll
?:
boolean
)
=>
{
setLoading
(
true
);
GoodsAPI
.
get
GoodsList
({
GoodsAPI
.
get
ListPageGoodsInfo
({
pageNo
:
pagination
.
pageNo
,
pageSize
:
pagination
.
pageSize
,
goodsType
:
0
,
...
query
,
}).
then
(({
result
})
=>
{
setLoading
(
false
);
...
...
@@ -202,48 +213,36 @@ const GoodsList = () => {
const
toGoodsDetail
=
(
id
:
number
)
=>
{
navigate
({
pathname
:
'/mallManage/mallGoods/detail'
,
search
:
`id=
${
id
}
&isDetail=1
`
,
search
:
`id=
${
id
}
`
,
});
};
// 表格多选事件
const
onSelectChange
=
(
newSelectedRowKeys
:
React
.
Key
[])
=>
{
setSelectedRowKeys
(
newSelectedRowKeys
);
};
//获取目录列表
const
getDirectoryList
=
()
=>
{
CategoryManageAPI
.
getDirectoryListClone
({
type
:
4
}).
then
(({
result
})
=>
{
if
(
result
)
{
const
options
=
result
.
map
((
v
)
=>
({
id
:
v
.
id
,
name
:
v
.
directoryName
}));
searchColumns
[
1
].
options
=
options
;
setSearchColumns
([...
searchColumns
]);
}
});
};
//商品-批量上下架
const
batchOnShelfOrTakeDown
=
(
status
:
number
)
=>
{
if
(
selectedRowKeys
.
length
===
0
)
{
return
message
.
warning
(
'请先选择商品'
);
}
GoodsAPI
.
batchOnShelfOrTakeDown
({
goodsIds
:
selectedRowKeys
as
number
[],
status
}).
then
(
({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
status
?
'上架成功'
:
'下架成功'
);
getGoodsList
(
query
);
setSelectedRowKeys
([]);
}
//商品-单个上下架
const
upOrDownShelf
=
(
status
:
number
,
id
:
number
)
=>
{
Modal
.
confirm
({
title
:
'提示'
,
content
:
`确认
${
status
?
'上架'
:
'下架'
}
该商品?`
,
onOk
:
()
=>
{
GoodsAPI
.
upOrDownShelf
({
id
,
status
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
status
?
'上架成功'
:
'下架成功'
);
getGoodsList
(
query
);
setSelectedRowKeys
([]);
}
});
},
);
}
);
};
//商品-删除
const
deleteGoods
=
()
=>
{
if
(
selectedRowKeys
.
length
===
0
)
{
return
message
.
warning
(
'请先选择商品'
);
}
const
removeMallGoods
=
(
id
:
number
)
=>
{
Modal
.
confirm
({
title
:
'提示'
,
content
:
'删除后数据将会丢失,确定删除吗?'
,
onOk
()
{
GoodsAPI
.
batchRemoveWareInfo
(
selectedRowKeys
as
number
[]
).
then
(({
code
})
=>
{
GoodsAPI
.
removeMallGoods
({
id
}
).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
if
(
pagination
.
pageNo
!==
1
&&
tableData
.
length
==
1
)
{
pagination
.
pageNo
-=
1
;
...
...
@@ -257,11 +256,9 @@ const GoodsList = () => {
});
};
//上移
const
upGoodsClick
=
()
=>
{
const
upGoodsClick
=
_
.
debounce
(
()
=>
{
if
(
selectedRowKeys
.
length
===
0
)
{
message
.
warning
(
'请选择商品'
);
}
else
if
(
selectedRowKeys
.
length
>
1
)
{
message
.
warning
(
'最多选择一个商品'
);
}
else
{
const
index
=
tableData
.
findIndex
((
v
)
=>
v
.
id
===
selectedRowKeys
[
0
]);
const
allIndex
=
allGoods
.
findIndex
((
v
)
=>
v
.
id
===
selectedRowKeys
[
0
]);
...
...
@@ -276,7 +273,7 @@ const GoodsList = () => {
:
tableData
.
filter
((
_v
,
i
)
=>
index
-
1
===
i
||
index
===
i
)
.
map
((
v
)
=>
({
id
:
v
.
id
}));
GoodsAPI
.
exchange
GoodsInfo
({
firstId
:
exReqData
[
0
].
id
,
secondId
:
exReqData
[
1
].
id
}).
then
(
GoodsAPI
.
exchange
({
firstId
:
exReqData
[
0
].
id
,
secondId
:
exReqData
[
1
].
id
}).
then
(
({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'上移成功'
);
...
...
@@ -287,7 +284,7 @@ const GoodsList = () => {
pageNo
:
pagination
.
pageNo
,
pageSize
:
pagination
.
pageSize
,
...
query
,
s
tatus
:
query
.
status
===
undefined
?
'all'
:
query
.
s
tatus
,
s
helfStatus
:
query
.
shelfStatus
===
undefined
?
'all'
:
query
.
shelfS
tatus
,
}),
);
}
...
...
@@ -298,13 +295,11 @@ const GoodsList = () => {
);
}
}
};
}
,
500
)
;
//下移
const
downGoodsClick
=
()
=>
{
const
downGoodsClick
=
_
.
debounce
(
()
=>
{
if
(
selectedRowKeys
.
length
===
0
)
{
message
.
warning
(
'请选择商品'
);
}
else
if
(
selectedRowKeys
.
length
>
1
)
{
message
.
warning
(
'最多选择一个商品'
);
}
else
{
const
index
=
tableData
.
findIndex
((
v
)
=>
v
.
id
===
selectedRowKeys
[
0
]);
const
allIndex
=
allGoods
.
findIndex
((
v
)
=>
v
.
id
===
selectedRowKeys
[
0
]);
...
...
@@ -319,7 +314,7 @@ const GoodsList = () => {
:
tableData
.
filter
((
_v
,
i
)
=>
index
+
1
===
i
||
index
===
i
)
.
map
((
v
)
=>
({
id
:
v
.
id
}));
GoodsAPI
.
exchange
GoodsInfo
({
firstId
:
exReqData
[
0
].
id
,
secondId
:
exReqData
[
1
].
id
}).
then
(
GoodsAPI
.
exchange
({
firstId
:
exReqData
[
0
].
id
,
secondId
:
exReqData
[
1
].
id
}).
then
(
({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'下移成功'
);
...
...
@@ -330,7 +325,7 @@ const GoodsList = () => {
pageNo
:
pagination
.
pageNo
,
pageSize
:
pagination
.
pageSize
,
...
query
,
s
tatus
:
query
.
status
===
undefined
?
'all'
:
query
.
s
tatus
,
s
helfStatus
:
query
.
shelfStatus
===
undefined
?
'all'
:
query
.
shelfS
tatus
,
}),
);
}
...
...
@@ -341,48 +336,66 @@ const GoodsList = () => {
);
}
}
},
500
);
//分类列表
const
getCategoryList
=
()
=>
{
CategoryManageAPI
.
getCategoryRespList
({
pageNo
:
1
,
pageSize
:
99999
}).
then
(({
result
})
=>
{
searchColumns
[
1
].
options
=
(
result
.
list
||
[]).
map
((
v
)
=>
({
id
:
v
.
id
,
name
:
v
.
name
}));
setSearchColumns
([...
searchColumns
]);
setCategoryList
(
result
.
list
||
[]);
});
};
//商品列表,分类组合
const
getCategoryStr
=
(
record
:
goodsType
[
0
])
=>
{
return
categoryList
.
reduce
((
pre
:
string
[],
cur
)
=>
{
if
(
cur
.
id
===
record
.
categoryPrimaryId
)
{
pre
.
push
(
cur
.
name
);
if
(
record
.
categorySubId
)
{
pre
.
push
(
cur
.
subDTOList
.
find
((
v
)
=>
v
.
id
===
record
.
categorySubId
)?.
name
||
''
);
}
}
return
pre
;
},
[])
.
join
(
'/'
);
};
useEffect
(()
=>
{
get
Direct
oryList
();
get
Categ
oryList
();
pagination
.
pageNo
=
Number
(
searchParams
.
get
(
'pageNo'
)
||
1
);
pagination
.
pageSize
=
Number
(
searchParams
.
get
(
'pageSize'
)
||
10
);
const
queryObj
=
{
goodsName
:
searchParams
.
get
(
'goodsName'
)
||
undefined
,
directoryId
:
searchParams
.
get
(
'directoryId'
)
?
Number
(
searchParams
.
get
(
'directoryId'
))
:
undefined
,
startTime
:
searchParams
.
get
(
'startTime'
)
||
undefined
,
endTime
:
searchParams
.
get
(
'endTime'
)
||
undefined
,
status
:
searchParams
.
get
(
'status'
)
===
'all'
||
searchParams
.
get
(
'status'
)
===
null
tradeName
:
searchParams
.
get
(
'goodsName'
)
||
undefined
,
shelfStatus
:
searchParams
.
get
(
'shelfStatus'
)
===
'all'
||
searchParams
.
get
(
'shelfStatus'
)
===
null
?
undefined
:
Number
(
searchParams
.
get
(
'status'
)),
:
Number
(
searchParams
.
get
(
's
helfS
tatus'
)),
};
getGoodsList
(
queryObj
);
getGoodsList
({
...
queryObj
,
pageNo
:
1
,
pageSize
:
9999
},
true
);
setActiveTabKey
(
searchParams
.
get
(
's
tatus'
)
===
'all'
||
searchParams
.
get
(
's
tatus'
)
===
null
searchParams
.
get
(
's
helfStatus'
)
===
'all'
||
searchParams
.
get
(
'shelfS
tatus'
)
===
null
?
'1'
:
Number
(
searchParams
.
get
(
'status'
))
===
1
:
Number
(
searchParams
.
get
(
's
helfS
tatus'
))
===
1
?
'2'
:
'3'
,
);
(
searchRef
.
current
as
any
).
getForm
().
setFieldsValue
({
goodsName
:
searchParams
.
get
(
'goodsName'
)
||
undefined
,
directoryId
:
searchParams
.
get
(
'directoryId'
)
?
Number
(
searchParams
.
get
(
'directoryId'
))
:
undefined
,
time
:
searchParams
.
get
(
'startTime'
)
?
[
searchParams
.
get
(
'startTime'
),
searchParams
.
get
(
'endTime'
)]
:
undefined
,
tradeName
:
searchParams
.
get
(
'goodsName'
)
||
undefined
,
});
},
[]);
return
(
<
div
className=
'goods-list'
>
<
SearchBox
search=
{
searchColumns
}
child=
{
<
Button
type=
'primary'
icon=
{
<
PlusOutlined
/>
}
onClick=
{
toAddMallGoods
}
>
<
Button
type=
'primary'
icon=
{
<
PlusOutlined
/>
}
onClick=
{
toAddMallGoods
}
disabled=
{
!!
userInfo
.
roleInfo
.
superAdmin
}
>
新增商品
</
Button
>
}
...
...
@@ -396,6 +409,7 @@ const GoodsList = () => {
style=
{
{
marginRight
:
'10px'
}
}
icon=
{
<
ArrowUpOutlined
/>
}
onClick=
{
upGoodsClick
}
disabled=
{
!!
userInfo
.
roleInfo
.
superAdmin
}
>
上移
</
Button
>
...
...
@@ -404,33 +418,10 @@ const GoodsList = () => {
style=
{
{
marginRight
:
'10px'
}
}
icon=
{
<
ArrowDownOutlined
/>
}
onClick=
{
downGoodsClick
}
disabled=
{
!!
userInfo
.
roleInfo
.
superAdmin
}
>
下移
</
Button
>
{
activeTabKey
!==
'2'
&&
(
<
Button
type=
'primary'
style=
{
{
marginRight
:
'10px'
}
}
icon=
{
<
ArrowUpOutlined
/>
}
onClick=
{
()
=>
batchOnShelfOrTakeDown
(
1
)
}
>
上架
</
Button
>
)
}
{
activeTabKey
!==
'3'
&&
(
<
Button
type=
'primary'
style=
{
{
marginRight
:
'10px'
}
}
icon=
{
<
ArrowDownOutlined
/>
}
onClick=
{
()
=>
batchOnShelfOrTakeDown
(
0
)
}
>
下架
</
Button
>
)
}
<
Button
danger
icon=
{
<
DeleteOutlined
/>
}
onClick=
{
deleteGoods
}
>
删除
</
Button
>
</
div
>
<
Table
columns=
{
tableColumns
}
...
...
@@ -440,6 +431,8 @@ const GoodsList = () => {
rowSelection=
{
{
selectedRowKeys
,
onChange
:
onSelectChange
,
type
:
'radio'
,
hideSelectAll
:
true
,
}
}
loading=
{
loading
}
pagination=
{
{
...
...
src/pages/systemManage/companyManage/companyDetail/components/addPeopleModal/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
FC
,
useState
}
from
'react'
;
import
{
Form
,
message
,
Modal
,
ModalProps
,
Select
}
from
'antd'
;
import
{
CommonAPI
,
SystemManageAPI
}
from
'~/api'
;
interface
selfProps
{
onOk
:
()
=>
void
;
companyInfoId
:
number
;
}
const
AddPeopleModal
:
FC
<
ModalProps
&
selfProps
>
=
({
open
,
onCancel
,
onOk
,
companyInfoId
})
=>
{
const
[
form
]
=
Form
.
useForm
<
{
userAccountId
:
number
}
>
();
const
[
options
,
setOptions
]
=
useState
<
{
label
:
string
;
value
:
number
;
key
:
string
}[]
>
([]);
const
handleOk
=
()
=>
{
form
.
validateFields
().
then
((
values
)
=>
{
SystemManageAPI
.
bindingCompanyMember
({
...
values
,
companyInfoId
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'绑定成功'
);
onOk
();
form
.
resetFields
();
}
});
});
};
//select 搜索
const
selectSearchEvent
=
(
value
:
string
)
=>
{
CommonAPI
.
getUserAccountByPhoneNum
({
phoneNum
:
value
}).
then
(({
result
})
=>
{
const
list
=
(
result
||
[]).
map
((
v
)
=>
({
label
:
v
.
phoneNum
+
`(
${
v
.
uid
}
)`
,
value
:
v
.
id
,
key
:
value
,
}));
setOptions
(
list
);
});
};
return
(
<
Modal
open=
{
open
}
title=
'添加成员'
onOk=
{
handleOk
}
onCancel=
{
onCancel
}
>
<
Form
form=
{
form
}
>
<
Form
.
Item
label=
'成员'
name=
'userAccountId'
rules=
{
[{
required
:
true
,
message
:
'请选择成员'
}]
}
>
<
Select
placeholder=
'请输入成员手机号码'
showSearch
onSearch=
{
selectSearchEvent
}
filterOption=
{
(
input
,
option
)
=>
(
option
?.
key
??
''
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
options=
{
options
}
></
Select
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
AddPeopleModal
;
src/pages/systemManage/companyManage/companyDetail/components/transferLeaderModal/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
Form
,
message
,
Modal
,
ModalProps
,
Select
}
from
'antd'
;
import
{
FC
,
useEffect
,
useState
}
from
'react'
;
import
{
SystemManageAPI
}
from
'~/api'
;
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
listCompanyMembersType
}
from
'~/api/interface/systemManageType'
;
//单位-成员列表返回类型
type
companyMembersType
=
InterDataType
<
listCompanyMembersType
>
[
'list'
];
interface
selfProps
{
onOk
:
()
=>
void
;
companyInfoId
:
number
;
currentCompanyMembers
:
companyMembersType
[
0
]
|
undefined
;
}
const
TransferLeaderModal
:
FC
<
ModalProps
&
selfProps
>
=
({
open
,
onOk
,
onCancel
,
companyInfoId
,
currentCompanyMembers
,
})
=>
{
const
[
form
]
=
Form
.
useForm
<
{
toUserAccountId
:
number
}
>
();
const
[
listCompanyMembers
,
setListCompanyMembers
]
=
useState
<
companyMembersType
>
([]);
const
handleOk
=
()
=>
{
form
.
validateFields
().
then
((
values
)
=>
{
if
(
currentCompanyMembers
)
{
SystemManageAPI
.
transferLeader
({
companyInfoId
,
fromUserAccountId
:
currentCompanyMembers
.
id
,
...
values
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'转让成功'
);
onOk
();
}
});
}
});
};
//单位成员列表
const
getListCompanyMembers
=
()
=>
{
SystemManageAPI
.
getListCompanyMembers
({
companyInfoId
,
pageNo
:
1
,
pageSize
:
999999
,
}).
then
(({
result
})
=>
{
setListCompanyMembers
((
result
.
list
||
[]).
filter
((
v
)
=>
!
v
.
leader
));
});
};
useEffect
(()
=>
{
if
(
currentCompanyMembers
)
{
getListCompanyMembers
();
}
},
[
currentCompanyMembers
]);
return
(
<
Modal
open=
{
open
}
title=
'转让管理员'
onCancel=
{
onCancel
}
onOk=
{
handleOk
}
>
<
Form
form=
{
form
}
>
<
Form
.
Item
label=
'转让人'
name=
'toUserAccountId'
>
<
Select
placeholder=
'请选择受让人'
filterOption=
{
(
input
,
option
)
=>
(
option
!
.
children
as
unknown
as
string
).
toLowerCase
().
includes
(
input
.
toLowerCase
())
}
>
{
listCompanyMembers
.
map
((
v
)
=>
(
<
Select
.
Option
key=
{
v
.
id
}
value=
{
v
.
id
}
>
{
v
.
phoneNum
}
(
{
v
.
uid
}
)
</
Select
.
Option
>
))
}
</
Select
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
TransferLeaderModal
;
src/pages/systemManage/companyManage/companyDetail/index.scss
0 → 100644
浏览文件 @
3018428e
.company-detail
{
position
:
relative
;
&
-info
{
margin-bottom
:
20px
;
}
&
-people
{
&
-title
{
line-height
:
50px
;
font-weight
:
bold
;
font-size
:
14px
;
}
&
-operate
{
margin-bottom
:
10px
;
}
}
&
-operate
{
position
:
absolute
;
right
:
0
;
top
:
0
;
}
}
src/pages/systemManage/companyManage/companyDetail/index.tsx
0 → 100644
浏览文件 @
3018428e
import
{
useSearchParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
useEffect
,
useState
}
from
'react'
;
import
{
SystemManageAPI
}
from
'~/api'
;
import
{
InterDataType
,
PaginationProps
}
from
'~/api/interface'
;
import
{
getCompanyInfoByIdType
,
listCompanyMembersType
}
from
'~/api/interface/systemManageType'
;
import
{
Button
,
Descriptions
,
message
,
Modal
,
Table
}
from
'antd'
;
import
'./index.scss'
;
import
{
ColumnsType
}
from
'antd/es/table'
;
import
{
PlusOutlined
}
from
'@ant-design/icons'
;
import
AddPeopleModal
from
'./components/addPeopleModal'
;
import
{
useSelector
}
from
'react-redux'
;
import
TransferLeaderModal
from
'~/pages/systemManage/companyManage/companyDetail/components/transferLeaderModal'
;
//单位详情-返回类型
type
companyDetailType
=
InterDataType
<
getCompanyInfoByIdType
>
;
//单位-成员列表返回类型
type
companyMembersType
=
InterDataType
<
listCompanyMembersType
>
[
'list'
];
const
CompanyDetail
=
()
=>
{
const
[
searchParams
]
=
useSearchParams
();
const
navigate
=
useNavigate
();
const
{
userInfo
}
=
useSelector
((
state
:
any
)
=>
state
.
UserInfo
);
const
tableColumns
:
ColumnsType
<
companyMembersType
[
0
]
>
=
[
{
title
:
'uid'
,
align
:
'center'
,
dataIndex
:
'uid'
,
},
{
title
:
'姓名'
,
align
:
'center'
,
dataIndex
:
'userName'
,
},
{
title
:
'角色'
,
align
:
'center'
,
dataIndex
:
'leader'
,
render
:
(
text
:
number
)
=>
(
text
?
'单位管理员'
:
'普通员工'
),
},
{
title
:
'手机号'
,
align
:
'center'
,
dataIndex
:
'phoneNum'
,
},
{
title
:
'操作'
,
width
:
'15%'
,
onHeaderCell
:
()
=>
({
style
:
{
textAlign
:
'center'
,
},
}),
render
:
(
_text
:
string
,
record
)
=>
(
<>
<
Button
type=
'link'
disabled=
{
!
userInfo
.
companyInfoVO
.
leader
||
!
record
.
leader
}
onClick=
{
()
=>
transferLeaderClick
(
record
)
}
>
转让
</
Button
>
<
Button
type=
'link'
disabled=
{
!
userInfo
.
companyInfoVO
.
leader
||
!!
record
.
leader
}
onClick=
{
()
=>
unbindCompanyClick
(
record
)
}
>
解绑
</
Button
>
</>
),
},
];
const
[
companyId
,
setCompanyId
]
=
useState
<
number
>
(
-
1
);
const
[
companyDetail
,
setCompanyDetail
]
=
useState
<
companyDetailType
>
();
const
[
pagination
,
setPagination
]
=
useState
<
PaginationProps
&
{
totalCount
:
number
}
>
({
pageNo
:
1
,
pageSize
:
10
,
totalCount
:
0
,
});
const
[
listCompanyMembers
,
setListCompanyMembers
]
=
useState
<
companyMembersType
>
([]);
const
[
currentCompanyMembers
,
setCurrentCompanyMembers
]
=
useState
<
companyMembersType
[
0
]
>
();
const
[
addPeopleModalShow
,
setAddPeopleModalShow
]
=
useState
<
boolean
>
(
false
);
const
[
transferLeaderModalShow
,
setTransferLeaderModalShow
]
=
useState
<
boolean
>
(
false
);
//单位详情
const
getCompanyDetailInfo
=
(
id
:
number
)
=>
{
SystemManageAPI
.
getCompanyInfoById
({
id
}).
then
(({
result
})
=>
{
setCompanyDetail
(
result
);
});
};
//单位成员列表
const
getListCompanyMembers
=
(
companyInfoId
:
number
)
=>
{
SystemManageAPI
.
getListCompanyMembers
({
companyInfoId
,
pageNo
:
pagination
.
pageNo
,
pageSize
:
pagination
.
pageSize
,
}).
then
(({
result
})
=>
{
pagination
.
totalCount
=
result
.
totalCount
;
setPagination
(
pagination
);
setListCompanyMembers
(
result
.
list
||
[]);
});
};
//分页
const
paginationChange
=
(
pageNo
:
number
,
pageSize
:
number
)
=>
{
pagination
.
pageNo
=
pageNo
;
pagination
.
pageSize
=
pageSize
;
getListCompanyMembers
(
companyId
);
};
//添加成员弹窗
const
addPeopleClick
=
()
=>
{
setAddPeopleModalShow
(
true
);
};
const
addPeopleModalOk
=
()
=>
{
getListCompanyMembers
(
companyId
);
setAddPeopleModalShow
(
false
);
};
const
addPeopleModalCancel
=
()
=>
{
setAddPeopleModalShow
(
false
);
};
//转让管理员弹窗
const
transferLeaderClick
=
(
record
:
companyMembersType
[
0
])
=>
{
setCurrentCompanyMembers
(
record
);
setTransferLeaderModalShow
(
true
);
};
const
transferLeaderModalCancel
=
()
=>
{
setTransferLeaderModalShow
(
false
);
};
const
transferLeaderModalOk
=
()
=>
{
setTransferLeaderModalShow
(
false
);
getListCompanyMembers
(
companyId
);
};
//接触绑定
const
unbindCompanyClick
=
(
record
:
companyMembersType
[
0
])
=>
{
Modal
.
confirm
({
title
:
'提示'
,
content
:
'确认解除绑定该成员?'
,
onOk
:
()
=>
{
SystemManageAPI
.
unbindCompanyMember
({
userAccountId
:
record
.
id
,
companyInfoId
:
companyId
,
}).
then
(({
code
})
=>
{
if
(
code
===
'200'
)
{
message
.
success
(
'解除成功'
);
if
(
pagination
.
pageNo
!==
1
&&
listCompanyMembers
?.
length
===
1
)
{
pagination
.
pageNo
-=
1
;
}
getListCompanyMembers
(
companyId
);
}
});
},
});
};
//返回
const
backRoute
=
()
=>
{
navigate
(
-
1
);
};
useEffect
(()
=>
{
setCompanyId
(
Number
(
searchParams
.
get
(
'id'
)));
getCompanyDetailInfo
(
Number
(
searchParams
.
get
(
'id'
)));
getListCompanyMembers
(
Number
(
searchParams
.
get
(
'id'
)));
},
[]);
return
(
<
div
className=
'company-detail'
>
<
div
className=
'company-detail-info'
>
<
Descriptions
title=
'基本信息'
bordered
column=
{
4
}
>
<
Descriptions
.
Item
label=
'单位名称'
>
{
companyDetail
?.
companyName
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'详细地址'
>
{
companyDetail
?.
address
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'联系人'
>
{
companyDetail
?.
companyUserName
||
''
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
'联系电话'
>
{
companyDetail
?.
phoneNum
||
''
}
</
Descriptions
.
Item
>
</
Descriptions
>
</
div
>
<
div
className=
'company-detail-people'
>
<
div
className=
'company-detail-people-title'
>
成员信息
</
div
>
<
div
className=
'company-detail-people-operate'
>
<
Button
type=
'primary'
icon=
{
<
PlusOutlined
></
PlusOutlined
>
}
onClick=
{
addPeopleClick
}
disabled=
{
!
userInfo
.
companyInfoVO
.
leader
}
>
添加成员
</
Button
>
</
div
>
<
Table
bordered
columns=
{
tableColumns
}
dataSource=
{
listCompanyMembers
}
pagination=
{
{
total
:
pagination
.
totalCount
,
pageSize
:
pagination
.
pageSize
,
current
:
pagination
.
pageNo
,
showSizeChanger
:
true
,
showQuickJumper
:
true
,
onChange
:
(
page
:
number
,
pageSize
:
number
)
=>
paginationChange
(
page
,
pageSize
),
showTotal
:
(
total
,
range
)
=>
`当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`
,
}
}
/>
</
div
>
<
div
className=
'company-detail-operate'
>
<
Button
type=
'primary'
onClick=
{
backRoute
}
>
返回
</
Button
>
</
div
>
{
/*添加成员*/
}
<
AddPeopleModal
open=
{
addPeopleModalShow
}
onCancel=
{
addPeopleModalCancel
}
onOk=
{
addPeopleModalOk
}
companyInfoId=
{
companyId
}
/>
{
/*转让管理员*/
}
<
TransferLeaderModal
open=
{
transferLeaderModalShow
}
onCancel=
{
transferLeaderModalCancel
}
onOk=
{
transferLeaderModalOk
}
companyInfoId=
{
companyId
}
currentCompanyMembers=
{
currentCompanyMembers
}
/>
</
div
>
);
};
export
default
CompanyDetail
;
src/pages/systemManage/companyManage/comp/addEditModal/index.tsx
→
src/pages/systemManage/companyManage/comp
anyList/comp
/addEditModal/index.tsx
浏览文件 @
3018428e
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
InterListType
,
InterReqType
}
from
'~/api/interface'
;
import
{
listCompanyAdd
,
listCompanyPage
}
from
'~/api/interface/systemManageType'
;
import
{
Cascader
,
Form
,
Input
,
message
,
Modal
}
from
'antd'
;
import
{
Button
,
Col
,
Form
,
Input
,
message
,
Modal
,
Row
}
from
'antd'
;
import
{
SystemManageAPI
}
from
'~/api'
;
import
DistrictData
from
'~/assets/json/district.json'
;
import
{
EnvironmentOutlined
}
from
'@ant-design/icons'
;
import
SelectMap
from
'~/components/select-map'
;
// 列表的类型
type
TableType
=
InterListType
<
listCompanyPage
>
;
// 请求的表单类型
type
ReqType
=
InterReqType
<
listCompanyAd
d
>
;
type
ReqType
=
Exclude
<
InterReqType
<
listCompanyAdd
>
,
undefine
d
>
;
// 传参类型
interface
propType
{
title
:
string
;
...
...
@@ -21,14 +22,15 @@ const AddEditModal: React.FC<propType> = (props) => {
const
{
title
,
open
,
closed
,
data
}
=
props
;
/// 表单钩子
const
[
form
]
=
Form
.
useForm
<
ReqType
>
();
// 地区
const
[
localList
,
setLocalList
]
=
useState
<
{
childInfo
:
any
[];
id
:
number
;
name
:
string
;
}[]
>
();
//选点信息
const
[
position
,
setPosition
]
=
useState
<
{
lat
:
number
;
lon
:
number
;
address
:
string
;
}
>
();
//地图选点弹窗
const
[
selectMapShow
,
setSelectMapShow
]
=
useState
<
boolean
>
(
false
);
// 关闭弹窗
const
handleCancel
=
()
=>
{
form
.
resetFields
();
...
...
@@ -39,13 +41,14 @@ const AddEditModal: React.FC<propType> = (props) => {
form
.
validateFields
()
.
then
(
async
(
values
)
=>
{
await
handleSubmit
({
...
values
,
province
:
values
?.
area
?.
at
(
0
),
city
:
values
?.
area
?.
at
(
1
),
district
:
values
?.
area
?.
at
(
2
),
companyType
:
data
?.
id
===
1
?
0
:
1
,
});
if
(
position
)
{
await
handleSubmit
({
...
values
,
lat
:
position
.
lat
,
lon
:
position
.
lon
,
companyType
:
data
?.
id
===
1
?
0
:
1
,
});
}
})
.
catch
((
err
)
=>
{
message
...
...
@@ -66,22 +69,40 @@ const AddEditModal: React.FC<propType> = (props) => {
handleCancel
();
}
};
// 获取地区信息
const
getSecondDistrictInfo
=
async
()
=>
{
setLocalList
(
DistrictData
||
[]);
const
selectMapShowClick
=
()
=>
{
setSelectMapShow
(
true
);
};
const
selectMapClose
=
()
=>
{
setSelectMapShow
(
false
);
};
const
selectMapSubmit
=
(
value
:
{
lat
:
number
;
lon
:
number
;
address
:
string
})
=>
{
form
.
setFieldValue
(
'address'
,
value
.
address
);
setPosition
(
value
);
setSelectMapShow
(
false
);
};
const
addressInputEvent
=
(
e
:
any
)
=>
{
if
(
position
)
{
position
.
address
=
e
.
target
.
value
;
form
.
setFieldValue
(
'address'
,
e
.
target
.
value
||
undefined
);
setPosition
({
...
position
});
}
};
// componentDidMount
useEffect
(()
=>
{
if
(
!
open
)
return
;
getSecondDistrictInfo
().
then
();
if
(
!
data
)
return
;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
form
.
setFieldsValue
({
...
data
,
area
:
[
data
?.
province
,
data
?.
city
,
data
?.
district
],
});
// console.log('data --->', data);
setPosition
({
address
:
data
.
address
,
lat
:
data
.
lat
,
lon
:
data
.
lon
,
});
},
[
open
]);
return
(
<
Modal
...
...
@@ -100,35 +121,55 @@ const AddEditModal: React.FC<propType> = (props) => {
>
<
Input
placeholder=
{
'请输入单位名称'
}
maxLength=
{
25
}
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'单位全称'
rules=
{
[{
required
:
false
,
message
:
'请输入单位全称'
}]
}
name=
'fullName'
>
<
Input
placeholder=
{
'请输入单位全称'
}
maxLength=
{
50
}
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'行政区划'
name=
'area'
rules=
{
[{
required
:
true
,
message
:
'请选择行政区划'
}]
}
>
<
Cascader
options=
{
localList
}
placeholder=
'请选择行政区划'
allowClear
fieldNames=
{
{
label
:
'name'
,
value
:
'name'
,
children
:
'childInfo'
,
}
}
/>
</
Form
.
Item
>
{
/*<Form.Item*/
}
{
/* label='单位全称'*/
}
{
/* rules={[{ required: false, message: '请输入单位全称' }]}*/
}
{
/* name='fullName'*/
}
{
/*>*/
}
{
/* <Input placeholder={'请输入单位全称'} maxLength={50} allowClear />*/
}
{
/*</Form.Item>*/
}
{
/*<Form.Item*/
}
{
/* label='行政区划'*/
}
{
/* name='area'*/
}
{
/* rules={[{ required: true, message: '请选择行政区划' }]}*/
}
{
/*>*/
}
{
/* <Cascader*/
}
{
/* options={localList}*/
}
{
/* placeholder='请选择行政区划'*/
}
{
/* allowClear*/
}
{
/* fieldNames={{*/
}
{
/* label: 'name',*/
}
{
/* value: 'name',*/
}
{
/* children: 'childInfo',*/
}
{
/* }}*/
}
{
/* />*/
}
{
/*</Form.Item>*/
}
<
Form
.
Item
label=
'详细地址'
name=
'address'
rules=
{
[{
required
:
true
,
message
:
'请输入详细地址'
}]
}
>
<
Input
.
TextArea
placeholder=
'请输入详细地址'
maxLength=
{
50
}
showCount
/>
{
/*<Input.TextArea placeholder='请输入详细地址' maxLength={50} showCount />*/
}
<
Row
justify=
'space-between'
>
{
position
?
(
<
Col
span=
{
21
}
>
<
Input
placeholder=
'请输入详细地址'
value=
{
position
.
address
}
onChange=
{
addressInputEvent
}
/>
</
Col
>
)
:
(
''
)
}
<
Col
span=
{
2
}
>
<
Button
icon=
{
<
EnvironmentOutlined
/>
}
type=
'primary'
onClick=
{
selectMapShowClick
}
></
Button
>
</
Col
>
</
Row
>
</
Form
.
Item
>
<
Form
.
Item
label=
'联系人'
name=
'companyUserName'
>
<
Input
placeholder=
'请输入联系人'
maxLength=
{
15
}
/>
...
...
@@ -152,6 +193,7 @@ const AddEditModal: React.FC<propType> = (props) => {
<
Form
.
Item
label=
'备注'
name=
'remark'
>
<
Input
.
TextArea
placeholder=
'请输入备注'
maxLength=
{
50
}
showCount
/>
</
Form
.
Item
>
<
SelectMap
open=
{
selectMapShow
}
closed=
{
selectMapClose
}
submit=
{
selectMapSubmit
}
/>
</
Form
>
</
Modal
>
);
...
...
src/pages/systemManage/companyManage/index.tsx
→
src/pages/systemManage/companyManage/
companyList/
index.tsx
浏览文件 @
3018428e
...
...
@@ -6,6 +6,7 @@ import { InterListType, InterReqType } from '~/api/interface';
import
{
ColumnsType
}
from
'antd/es/table'
;
import
{
SystemManageAPI
}
from
'~/api'
;
import
{
listCompanyPage
}
from
'~/api/interface/systemManageType'
;
import
{
useNavigate
}
from
'react-router-dom'
;
import
AddEditModal
from
'./comp/addEditModal'
;
// 列表的数据类型
...
...
@@ -16,6 +17,7 @@ type ReqType = InterReqType<listCompanyPage>;
let
query
:
ReqType
=
{};
const
CompanyManageView
=
()
=>
{
const
navigate
=
useNavigate
();
const
{
confirm
}
=
Modal
;
// 新增编辑弹窗是否开启
const
[
addEditModalVisible
,
setAddEditModalVisible
]
=
useState
(
false
);
...
...
@@ -63,7 +65,7 @@ const CompanyManageView = () => {
// 删除单位
const
handleDelete
=
(
value
:
TableType
[
0
])
=>
{
confirm
({
title
:
'提示'
,
title
:
'提示
(删除会造成该单位下的商品全部删除)
'
,
content
:
'是否删除该单位?'
,
onOk
:
async
()
=>
{
const
res
=
await
SystemManageAPI
.
listCompanyRemove
({
id
:
value
.
id
});
...
...
@@ -77,6 +79,14 @@ const CompanyManageView = () => {
},
});
};
//跳转单位详情
const
toCompanyDetail
=
(
record
:
TableType
[
0
])
=>
{
navigate
({
pathname
:
'/systemManage/companyDetail'
,
search
:
`id=
${
record
.
id
}
`
,
});
};
// componentDidMount
useEffect
(()
=>
{
query
=
{};
...
...
@@ -88,17 +98,11 @@ const CompanyManageView = () => {
title
:
'单位名称'
,
dataIndex
:
'companyName'
,
align
:
'center'
,
width
:
'
150px
'
,
width
:
'
20%
'
,
fixed
:
'left'
,
ellipsis
:
true
,
},
{
title
:
'行政区划'
,
dataIndex
:
'province'
,
align
:
'center'
,
render
:
(
_value
,
record
)
=>
`
${
record
.
province
}
/
${
record
.
city
}
/
${
record
.
district
}
`
,
},
{
title
:
'详细地址'
,
dataIndex
:
'address'
,
align
:
'center'
,
...
...
@@ -117,7 +121,7 @@ const CompanyManageView = () => {
},
{
title
:
'操作'
,
width
:
'
100px
'
,
width
:
'
20%
'
,
fixed
:
'right'
,
align
:
'center'
,
render
:
(
_text
,
record
)
=>
(
...
...
@@ -131,6 +135,9 @@ const CompanyManageView = () => {
>
变更
</
Button
>
<
Button
type=
'link'
onClick=
{
()
=>
toCompanyDetail
(
record
)
}
>
详情
</
Button
>
<
Button
type=
'link'
danger
...
...
src/router/index.ts
浏览文件 @
3018428e
...
...
@@ -3,44 +3,40 @@ import { RouteObjectType, routerList } from '~/router/router';
import
{
InterDataType
}
from
'~/api/interface'
;
import
{
listMenuInfoType
}
from
'~/api/interface/systemManageType'
;
import
{
SystemManageAPI
}
from
'~/api'
;
import
Cookies
from
'js-cookie'
;
import
{
store
}
from
'~/store'
;
import
{
SET_MENU
}
from
'~/store/module/menu'
;
//菜单类型
type
menuType
=
InterDataType
<
listMenuInfoType
>
;
// 缓存路由列表
let
routerListStore
:
any
[]
=
[];
// 获取用户权限路由列表
export
const
authRouterList
=
async
()
=>
{
if
(
localStorage
.
getItem
(
'roleId'
)
&&
Cookies
.
get
(
'SHAREFLY-TOKEN'
))
{
// 如果缓存中没有数据
if
(
routerListStore
.
length
===
0
)
{
// 加载路由数据
const
{
result
}
=
await
SystemManageAPI
.
getListRoleMenuInfo
({
roleId
:
Number
(
localStorage
.
getItem
(
'roleId'
)),
});
const
ids
:
number
[]
=
getAllKeys
([
result
]);
const
getRouteList
=
(
data
:
RouteObjectType
[])
=>
{
return
data
.
reduce
((
pre
:
RouteObjectType
[],
cur
)
=>
{
const
Obj
:
RouteObjectType
=
{
...
cur
};
if
(
ids
.
includes
(
Obj
.
meta
.
id
)
||
Obj
.
meta
.
hidden
)
{
if
(
Obj
.
children
)
{
Obj
.
children
=
[...
getRouteList
(
Obj
.
children
)];
}
pre
.
push
(
Obj
);
// 如果缓存中没有数据
if
(
store
.
getState
().
Menu
.
menuList
.
length
===
0
)
{
// 加载路由数据
const
{
result
}
=
await
SystemManageAPI
.
getListRoleMenuInfo
({
roleId
:
Number
(
localStorage
.
getItem
(
'roleId'
)),
});
const
ids
:
number
[]
=
getAllKeys
([
result
]);
const
getRouteList
=
(
data
:
RouteObjectType
[])
=>
{
return
data
.
reduce
((
pre
:
RouteObjectType
[],
cur
)
=>
{
const
Obj
:
RouteObjectType
=
{
...
cur
};
if
(
ids
.
includes
(
Obj
.
meta
.
id
)
||
Obj
.
meta
.
hidden
)
{
if
(
Obj
.
children
)
{
Obj
.
children
=
[...
getRouteList
(
Obj
.
children
)];
}
return
pre
;
},
[]);
};
const
arr
=
[...
getRouteList
(
routerList
)];
// 将路由数据存到store中
routerListStore
=
arr
;
// 完成后返回路由数据
return
Promise
.
resolve
(
arr
);
}
else
{
return
Promise
.
resolve
(
routerListStore
);
}
pre
.
push
(
Obj
);
}
return
pre
;
},
[]);
};
const
arr
=
[...
getRouteList
(
routerList
)];
// 将路由数据存到store中
store
.
dispatch
(
SET_MENU
(
arr
));
// 完成后返回路由数据
return
Promise
.
resolve
(
arr
);
}
else
{
return
Promise
.
resolve
(
store
.
getState
().
Menu
.
menuList
);
}
return
Promise
.
resolve
([]);
};
//获取全部节点
const
getAllKeys
=
(
data
:
menuType
[])
=>
{
...
...
src/router/privateRouter.tsx
浏览文件 @
3018428e
...
...
@@ -14,23 +14,29 @@ function PrivateRouter() {
// TODO: 判断是否登录 (需要改为实时获取地址栏的路由)
const
path
=
location
.
pathname
;
const
token
=
Cookies
.
get
(
'SHAREFLY-TOKEN'
);
const
roleId
=
localStorage
.
getItem
(
'roleId'
);
if
(
!
token
&&
path
!==
'/login'
)
{
navigate
(
'/login'
,
{
replace
:
true
});
return
;
}
if
(
roleId
&&
token
)
{
// 整合路由数据
authRouterList
().
then
((
value
)
=>
{
if
(
value
.
length
)
{
const
routes
=
[...
value
,
...
whiteRouterList
];
setRouter
(
routes
);
if
(
path
===
'/'
)
{
navigate
({
pathname
:
value
[
0
].
children
?.
find
((
v
:
any
)
=>
!
v
.
meta
.
hidden
)?.
path
});
}
}
else
{
message
.
warning
(
'该账号暂无权限'
);
navigate
(
'/login'
,
{
replace
:
true
});
}
});
}
};
useEffect
(()
=>
{
beforeEach
();
// 整合路由数据
authRouterList
().
then
((
value
)
=>
{
if
(
value
.
length
)
{
const
routes
=
[...
value
,
...
whiteRouterList
];
setRouter
(
routes
);
//不同账号登录时,重新更新路由(有瑕疵)
}
else
if
(
localStorage
.
getItem
(
'roleId'
))
{
message
.
warning
(
'该账号暂无权限'
);
navigate
(
'/login'
,
{
replace
:
true
});
}
});
},
[
location
.
pathname
]);
return
useRoutes
(
router
);
...
...
src/router/router.tsx
浏览文件 @
3018428e
...
...
@@ -91,13 +91,16 @@ const RentAddOrEditOrDetailView = React.lazy(
const
MallGoodsView
=
React
.
lazy
(()
=>
import
(
'~/pages/mallManage/mallGoods/goodsList'
));
//商城商品
const
MallAddOrEditOrDetailView
=
React
.
lazy
(
()
=>
import
(
'~/pages/mallManage/mallGoods/goodsAddOrEditOrDetail'
),
);
//商城商品新增、编辑、详情
);
//商城商品新增、编辑、租赁商品详情
const
MallGoodsDetailsView
=
React
.
lazy
(()
=>
import
(
'~/pages/mallManage/mallGoods/goodsDetails'
));
//商城商品(新)
const
ProduceListView
=
React
.
lazy
(()
=>
import
(
'~/pages/mallManage/produceManage/produceList'
));
//产品列表
const
ProduceDetailView
=
React
.
lazy
(
()
=>
import
(
'~/pages/mallManage/produceManage/produceDetail'
),
);
//产品详情
const
MakeListView
=
React
.
lazy
(()
=>
import
(
'~/pages/mallManage/makeManage/makeList'
));
// 分类管理
const
CategoryListView
=
React
.
lazy
(()
=>
import
(
'~/pages/categoryManage/categoryList'
));
const
CategoryManage
=
React
.
lazy
(()
=>
import
(
'~/pages/categoryManage/category'
));
const
CategoryDetail
=
React
.
lazy
(()
=>
import
(
'~/pages/categoryManage/category/detail'
));
// 目录管理
...
...
@@ -119,7 +122,10 @@ import TenderManageDetail from '~/pages/resourceManage/tenderManage/detail';
import
TenderManageFeedback
from
'~/pages/resourceManage/tenderManage/feedback'
;
import
BusinessCaseManage
from
'~/pages/resourceManage/businessCaseManage'
;
import
CustomIdentityView
from
'~/pages/customManage/customIdentity'
;
import
CompanyManageView
from
'~/pages/systemManage/companyManage'
;
import
CompanyListView
from
'~/pages/systemManage/companyManage/companyList'
;
//单位列表
const
CompanyDetailView
=
React
.
lazy
(
()
=>
import
(
'~/pages/systemManage/companyManage/companyDetail'
),
);
import
AccountLimit
from
'~/pages/systemManage/limitManage/roleList'
;
//账号权限
import
LimitInfo
from
'~/pages/systemManage/limitManage/limitInfo'
;
import
CustomListDetail
from
'~/pages/customManage/customList/detail'
;
//权限信息
...
...
@@ -467,16 +473,6 @@ export const routerList: Array<RouteObjectType> = [
},
children
:
[
{
path
:
'/mallManage/courseManage'
,
element
:
withLoadingComponent
(<
CourseManageView
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
1010
,
icon
:
<
BookOutlined
/>,
title
:
'课程管理'
,
},
},
{
path
:
'/mallManage/serviceList'
,
element
:
withLoadingComponent
(<
ServiceListView
/>),
errorElement
:
<
ErrorPage
/>,
...
...
@@ -585,7 +581,7 @@ export const routerList: Array<RouteObjectType> = [
},
{
path
:
'/mallManage/mallGoods/detail'
,
element
:
withLoadingComponent
(<
Mall
AddOrEditOrDetail
View
/>),
element
:
withLoadingComponent
(<
Mall
GoodsDetails
View
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
10146
,
...
...
@@ -687,8 +683,8 @@ export const routerList: Array<RouteObjectType> = [
},
},
{
path
:
'/categoryManage/
jobServicesCategory/4
'
,
element
:
withLoadingComponent
(<
Category
Manage
/>),
path
:
'/categoryManage/
categoryList
'
,
element
:
withLoadingComponent
(<
Category
ListView
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
1240
,
...
...
@@ -696,6 +692,16 @@ export const routerList: Array<RouteObjectType> = [
icon
:
<
AppstoreOutlined
/>,
},
},
// {
// path: '/categoryManage/jobServicesCategory/4',
// element: withLoadingComponent(<CategoryManage />),
// errorElement: <ErrorPage />,
// meta: {
// id: 1240,
// title: '产品商城分类',
// icon: <AppstoreOutlined />,
// },
// },
{
path
:
'/categoryManage/jobServicesCategory/0'
,
element
:
withLoadingComponent
(<
CategoryManage
/>),
...
...
@@ -903,7 +909,7 @@ export const routerList: Array<RouteObjectType> = [
meta
:
{
id
:
1600
,
icon
:
<
BankOutlined
/>,
title
:
'
飞手
培训'
,
title
:
'
执照
培训'
,
},
children
:
[
{
...
...
@@ -938,6 +944,16 @@ export const routerList: Array<RouteObjectType> = [
hidden
:
true
,
},
},
{
path
:
'/pilotTraining/courseManage'
,
element
:
withLoadingComponent
(<
CourseManageView
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
1010
,
icon
:
<
BookOutlined
/>,
title
:
'课程管理'
,
},
},
],
},
{
...
...
@@ -982,13 +998,24 @@ export const routerList: Array<RouteObjectType> = [
},
},
{
path
:
'/systemManage/company
Manage
'
,
element
:
withLoadingComponent
(<
Company
Manage
View
/>),
path
:
'/systemManage/company
List
'
,
element
:
withLoadingComponent
(<
Company
List
View
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
1430
,
title
:
'单位管理'
,
title
:
'单位列表'
,
icon
:
<
BankOutlined
/>,
},
},
{
path
:
'/systemManage/companyDetail'
,
element
:
withLoadingComponent
(<
CompanyDetailView
/>),
errorElement
:
<
ErrorPage
/>,
meta
:
{
id
:
1440
,
title
:
'单位详情'
,
icon
:
<
BankOutlined
/>,
hidden
:
true
,
},
},
],
...
...
src/store/module/menu/index.ts
浏览文件 @
3018428e
import
{
createSlice
}
from
'@reduxjs/toolkit'
;
const
initialState
=
{
menuList
:
JSON
.
parse
(
localStorage
.
getItem
(
'SXTB-ADMIN-MENU-LIST'
)
as
string
)
||
[],
menuList
:
[],
collapsedActive
:
false
,
menuId
:
JSON
.
parse
(
localStorage
.
getItem
(
'SXTB-ADMIN-MENU-ID'
)
as
string
)
||
null
,
roleId
:
localStorage
.
getItem
(
'roleId'
)
?
Number
(
localStorage
.
getItem
(
'roleId'
))
:
-
1
,
};
export
const
menuSlice
=
createSlice
({
...
...
@@ -12,22 +12,19 @@ export const menuSlice = createSlice({
reducers
:
{
SET_MENU
(
state
,
action
)
{
state
.
menuList
=
action
.
payload
;
localStorage
.
setItem
(
'SXTB-ADMIN-MENU-LIST'
,
JSON
.
stringify
(
action
.
payload
));
},
SET_COLLAPSE
(
state
,
action
)
{
state
.
collapsedActive
=
action
.
payload
;
},
REMOVE_MENU
(
state
)
{
localStorage
.
setItem
(
'SXTB-ADMIN-MENU-LIST'
,
JSON
.
stringify
([]));
state
.
menuList
=
[];
},
SET_MENU_ID
(
state
,
action
)
{
localStorage
.
setItem
(
'SXTB-ADMIN-MENU-ID'
,
JSON
.
stringify
(
action
.
payload
))
;
state
.
menuId
=
action
.
payload
;
state
.
roleId
=
action
.
payload
;
localStorage
.
setItem
(
'roleId'
,
action
.
payload
)
;
},
REMOVE_MENU_ID
(
state
)
{
localStorage
.
setItem
(
'SXTB-ADMIN-MENU-ID'
,
JSON
.
stringify
(
null
));
state
.
menuId
=
null
;
REMOVE_MENU_ID
()
{
localStorage
.
removeItem
(
'roleId'
);
},
},
});
...
...
src/store/module/userInfo/index.ts
浏览文件 @
3018428e
...
...
@@ -2,8 +2,6 @@ import { createSlice } from '@reduxjs/toolkit';
const
initialState
=
{
userInfo
:
JSON
.
parse
(
localStorage
.
getItem
(
'SXTB-ADMIN-USER-INFO'
)
as
string
)
||
[],
roleId
:
-
1
,
roleList
:
[],
};
export
const
userInfoSlice
=
createSlice
({
...
...
@@ -14,24 +12,9 @@ export const userInfoSlice = createSlice({
state
.
userInfo
=
action
.
payload
;
localStorage
.
setItem
(
'SXTB-ADMIN-USER-INFO'
,
JSON
.
stringify
(
action
.
payload
));
},
SET_ROLE_ID
(
state
,
action
)
{
state
.
roleId
=
action
.
payload
;
localStorage
.
setItem
(
'roleId'
,
action
.
payload
);
},
REMOVE_ROLE_ID
()
{
localStorage
.
removeItem
(
'roleId'
);
},
SET_ROLE_LIST
(
state
,
action
)
{
state
.
roleList
=
action
.
payload
;
localStorage
.
setItem
(
'roleObj'
,
JSON
.
stringify
(
action
.
payload
));
},
REMOVE_ROLE_LIST
()
{
localStorage
.
removeItem
(
'roleObj'
);
},
},
});
export
const
{
SET_USERINFO
,
SET_ROLE_ID
,
SET_ROLE_LIST
,
REMOVE_ROLE_LIST
,
REMOVE_ROLE_ID
}
=
userInfoSlice
.
actions
;
export
const
{
SET_USERINFO
}
=
userInfoSlice
.
actions
;
export
const
UserInfo
=
userInfoSlice
.
reducer
;
src/utils/validateUtils.ts
浏览文件 @
3018428e
import
_
from
'lodash'
;
// 不能输入数字,其他可以输入
export
const
exceptNumber
=
(
val
:
any
)
=>
{
val
.
target
.
value
=
val
.
target
.
value
.
replace
(
/1
?(\d
|
([
1-9
]\d
+
))(
.
\d
+
)?
$/g
,
''
).
replace
(
/
\s
/g
,
''
);
...
...
@@ -105,3 +107,13 @@ export const maxLength6 = (val: any) => {
val
.
target
.
value
=
val
.
target
.
value
.
replace
(
/
\D
/g
,
''
);
}
};
//通用价格,且保留两位小数正则
export
const
regPriceNumber
=
(
value
:
string
):
boolean
=>
{
const
reg
=
/^
\d
+
(\.\d{1,2})?
$/
;
return
reg
.
test
(
value
);
};
//判断空值
export
const
isEmptyBol
=
(
value
:
any
):
boolean
=>
{
return
_
.
isNull
(
value
)
||
_
.
isNaN
(
value
)
||
_
.
isNull
(
value
)
||
_
.
isUndefined
(
value
);
};
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论