Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
e0b68607
authored
Jul 20, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user ui
parent
9fefaa8e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
310 additions
and
345 deletions
+310
-345
client/src/components/Icon/icons/light/billRecord.svg
+2
-0
client/src/components/Icon/icons/light/inform.svg
+2
-0
client/src/components/Icon/icons/light/loginout.svg
+2
-0
client/src/components/Icon/icons/light/payRecord.svg
+0
-0
client/src/components/Icon/index.tsx
+5
-1
client/src/hooks/useScreen.ts
+0
-21
client/src/pages/kb/detail/index.tsx
+2
-2
client/src/pages/number/components/BillTable.tsx
+9
-6
client/src/pages/number/components/Info.tsx
+139
-0
client/src/pages/number/components/InformTable.tsx
+36
-42
client/src/pages/number/components/PayRecordTable.tsx
+35
-34
client/src/pages/number/components/PromotionTable.tsx
+0
-67
client/src/pages/number/index.tsx
+78
-172
No files found.
client/src/components/Icon/icons/light/billRecord.svg
0 → 100644
View file @
e0b68607
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1689854058748"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"3614"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M803.84 934.4H238.08c-52.736 0-96.256-43.008-96.256-96.256V165.376c0-52.736 43.008-96.256 96.256-96.256H803.84c52.736 0 96.256 43.008 96.256 96.256v673.28c0 52.736-43.52 95.744-96.256 95.744zM232.96 128c-17.408 0-32.256 14.336-32.256 32.256v683.52c0 17.408 14.336 32.256 32.256 32.256H808.96c17.408 0 32.256-14.336 32.256-32.256V160.256c0-17.408-14.336-32.256-32.256-32.256H232.96z m256 646.656c-8.192 0-15.872-3.072-22.528-9.728l-48.128-46.592-24.064 15.872c-4.608 4.608-11.264 6.656-17.408 6.656h-48.128c-22.016-5.12-31.744-13.312-31.744-27.136 0-17.408 9.216-32.256 31.744-32.256h38.4l36.864-30.72c12.8-9.728 30.208-8.192 41.472 3.072l48.128 46.592 25.6-17.408c4.608-3.072 11.264-6.656 17.408-6.656h79.872c17.408 0 32.256 14.336 32.256 32.256 0 17.408-14.336 32.256-32.256 32.256h-70.656l-39.936 27.136c-4.096 5.12-10.24 6.656-16.896 6.656z"
p-id=
"3615"
></path><path
d=
"M718.336 385.536H316.416c-16.384 0-29.184-13.312-29.184-29.184 0-16.384 13.312-29.184 29.184-29.184h401.92c16.384 0 29.184 13.312 29.184 29.184 0.512 15.872-12.8 29.184-29.184 29.184zM718.336 535.04H316.416c-16.384 0-29.184-13.312-29.184-29.184 0-16.384 13.312-29.696 29.184-29.696h401.92c16.384 0 29.184 13.312 29.184 29.696 0.512 16.384-12.8 29.184-29.184 29.184z"
p-id=
"3616"
></path></svg>
\ No newline at end of file
client/src/components/Icon/icons/light/inform.svg
0 → 100644
View file @
e0b68607
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1689854044643"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"3460"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M892.1 805L781.9 621.3V458c0-71.8-28.1-139.5-79.3-190.6-36.2-36.2-80.7-60.8-129-72.2v-22.7c0-34-27.6-61.6-61.6-61.6s-61.6 27.6-61.6 61.6v22.7c-48.4 11.3-92.9 36-129 72.2-51.1 51.1-79.3 118.8-79.3 190.6v163.3L131.9 805h257.7c7.6 60.8 59.5 108 122.3 108s114.8-47.2 122.3-108h257.9zM496.4 172.6c0-8.6 7-15.6 15.6-15.6s15.6 7 15.6 15.6v16c-5.2-0.3-10.4-0.5-15.6-0.5s-10.4 0.2-15.6 0.5v-16zM288.1 634.1V458c0-123.4 100.4-223.9 223.9-223.9 123.4 0 223.9 100.4 223.9 223.9v176.1L810.8 759H213.2l74.9-124.9zM512 867c-37.4 0-68.6-26.7-75.8-62h151.5c-7.1 35.3-38.3 62-75.7 62z"
p-id=
"3461"
></path></svg>
\ No newline at end of file
client/src/components/Icon/icons/light/loginout.svg
0 → 100644
View file @
e0b68607
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1689855121257"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"3135"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M952.7 492.1c-1.4-1.8-3.1-3.4-4.8-4.9l-179-178.9c-12.5-12.5-32.9-12.5-45.4 0s-12.5 32.9 0 45.4l126 126H421.3h-0.1c-18.2 0-32.9 14.8-32.9 33s14.7 33 32.9 33c0.3 0.1 0.5 0 0.7 0h427.8l-126 126c-12.3 12.3-12.3 32.4 0 44.7l0.7 0.7c12.3 12.3 32.4 12.3 44.7 0l182-182c11.7-11.7 12.3-30.6 1.6-43z"
fill=
"#515151"
p-id=
"3136"
></path><path
d=
"M562.3 799c-18 0-32.7 14.7-32.7 32.7v63.8H129.2V128.7h400.4v63.1c0 18 14.7 32.7 32.7 32.7s32.7-14.7 32.7-32.7V96.3c0-3.5-0.6-6.8-1.6-10-4.2-13.3-16.6-23-31.2-23H96.6c-18 0-32.7 14.7-32.7 32.7v831.9c0 14.2 9.2 26.3 21.8 30.8 3.6 1.4 7.5 2.1 11.5 2.1h463.2c0.6 0 1.3 0.1 1.9 0.1 18 0 32.7-14.7 32.7-32.7v-96.5c0-18-14.7-32.7-32.7-32.7z"
fill=
"#515151"
p-id=
"3137"
></path><path
d=
"M256.8 512.7a32.9 33 0 1 0 65.8 0 32.9 33 0 1 0-65.8 0Z"
fill=
"#515151"
p-id=
"3138"
></path></svg>
\ No newline at end of file
client/src/components/Icon/icons/light/payRecord.svg
0 → 100644
View file @
e0b68607
This diff is collapsed.
Click to expand it.
client/src/components/Icon/index.tsx
View file @
e0b68607
...
...
@@ -63,7 +63,11 @@ const map = {
qaImport
:
require
(
'./icons/file/qaImport.svg'
).
default
,
uploadFile
:
require
(
'./icons/file/uploadFile.svg'
).
default
,
closeLight
:
require
(
'./icons/light/close.svg'
).
default
,
customTitle
:
require
(
'./icons/light/customTitle.svg'
).
default
customTitle
:
require
(
'./icons/light/customTitle.svg'
).
default
,
billRecordLight
:
require
(
'./icons/light/billRecord.svg'
).
default
,
informLight
:
require
(
'./icons/light/inform.svg'
).
default
,
payRecordLight
:
require
(
'./icons/light/payRecord.svg'
).
default
,
loginoutLight
:
require
(
'./icons/light/loginout.svg'
).
default
};
export
type
IconName
=
keyof
typeof
map
;
...
...
client/src/hooks/useScreen.ts
deleted
100644 → 0
View file @
9fefaa8e
import
{
useMemo
}
from
'react'
;
import
{
useMediaQuery
}
from
'@chakra-ui/react'
;
interface
Props
{
defaultIsPc
?:
boolean
;
}
export
function
useScreen
(
data
?:
Props
)
{
const
{
defaultIsPc
=
false
}
=
data
||
{};
const
[
isPc
]
=
useMediaQuery
(
'(min-width: 900px)'
,
{
ssr
:
false
,
fallback
:
defaultIsPc
});
return
{
isPc
,
mediaLgMd
:
useMemo
(()
=>
(
isPc
?
'lg'
:
'md'
),
[
isPc
]),
mediaMdSm
:
useMemo
(()
=>
(
isPc
?
'md'
:
'sm'
),
[
isPc
]),
media
:
(
pc
:
any
,
phone
:
any
)
=>
(
isPc
?
pc
:
phone
)
};
}
client/src/pages/kb/detail/index.tsx
View file @
e0b68607
...
...
@@ -6,8 +6,8 @@ import { useForm } from 'react-hook-form';
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
useScreen
}
from
'@/hooks/useScreen'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
type
ComponentRef
}
from
'./components/Info'
;
import
Tabs
from
'@/components/Tabs'
;
import
dynamic
from
'next/dynamic'
;
...
...
@@ -37,7 +37,7 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
const
theme
=
useTheme
();
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
{
isPc
}
=
use
Screen
();
const
{
isPc
}
=
use
GlobalStore
();
const
{
kbDetail
,
getKbDetail
}
=
useUserStore
();
const
tabList
=
useRef
([
...
...
client/src/pages/number/components/BillTable.tsx
View file @
e0b68607
...
...
@@ -21,6 +21,7 @@ import MyIcon from '@/components/Icon';
import
DateRangePicker
,
{
type
DateRangeType
}
from
'@/components/DateRangePicker'
;
import
{
addDays
}
from
'date-fns'
;
import
dynamic
from
'next/dynamic'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
const
BillDetail
=
dynamic
(()
=>
import
(
'./BillDetail'
));
...
...
@@ -30,6 +31,7 @@ const BillTable = () => {
from
:
addDays
(
new
Date
(),
-
7
),
to
:
new
Date
()
});
const
{
isPc
}
=
useGlobalStore
();
const
{
data
:
bills
,
...
...
@@ -38,6 +40,7 @@ const BillTable = () => {
getData
}
=
usePagination
<
UserBillType
>
({
api
:
getUserBills
,
pageSize
:
isPc
?
20
:
10
,
params
:
{
dateStart
:
new
Date
(
dateRange
.
from
||
new
Date
()).
setHours
(
0
,
0
,
0
,
0
),
dateEnd
:
new
Date
(
dateRange
.
to
||
new
Date
()).
setHours
(
23
,
59
,
59
,
999
)
...
...
@@ -47,8 +50,8 @@ const BillTable = () => {
const
[
billDetail
,
setBillDetail
]
=
useState
<
UserBillType
>
();
return
(
<>
<
TableContainer
p
osition=
{
'relative'
}
minH=
{
'100px
'
}
>
<
Flex
flexDirection=
{
'column'
}
py=
{
[
0
,
5
]
}
h=
{
'100%'
}
position=
{
'relative'
}
>
<
TableContainer
p
x=
{
[
3
,
8
]
}
position=
{
'relative'
}
flex=
{
'1 0 0'
}
h=
{
0
}
overflowY=
{
'auto
'
}
>
<
Table
>
<
Thead
>
<
Tr
>
...
...
@@ -78,27 +81,27 @@ const BillTable = () => {
</
TableContainer
>
{
!
isLoading
&&
bills
.
length
===
0
&&
(
<
Flex
h=
{
'100%
'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
>
<
Flex
flex=
{
'1 0 0
'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
无使用记录~
</
Box
>
</
Flex
>
)
}
<
Flex
w=
{
'100%'
}
mt=
{
4
}
justifyContent=
{
'flex-end'
}
flexWrap=
{
'wrap
'
}
>
<
Flex
w=
{
'100%'
}
mt=
{
4
}
px=
{
[
3
,
8
]
}
alignItems=
{
'center'
}
justifyContent=
{
'flex-end
'
}
>
<
DateRangePicker
defaultDate=
{
dateRange
}
position=
"top"
onChange=
{
setDateRange
}
onSuccess=
{
()
=>
getData
(
1
)
}
/>
<
Box
ml=
{
[
0
,
2
]
}
mt=
{
[
3
,
0
]
}
w=
{
[
'100%'
,
'auto'
]
}
>
<
Box
ml=
{
3
}
>
<
Pagination
/>
</
Box
>
</
Flex
>
<
Loading
loading=
{
isLoading
}
fixed=
{
false
}
/>
{
!!
billDetail
&&
<
BillDetail
bill=
{
billDetail
}
onClose=
{
()
=>
setBillDetail
(
undefined
)
}
/>
}
</>
</
Flex
>
);
};
...
...
client/src/pages/number/components/Info.tsx
0 → 100644
View file @
e0b68607
import
React
,
{
useCallback
}
from
'react'
;
import
{
Box
,
Flex
,
Button
,
useDisclosure
}
from
'@chakra-ui/react'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
UserUpdateParams
}
from
'@/types/user'
;
import
{
putUserInfo
}
from
'@/api/user'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
UserType
}
from
'@/types/user'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
dynamic
from
'next/dynamic'
;
import
{
useSelectFile
}
from
'@/hooks/useSelectFile'
;
import
{
compressImg
}
from
'@/utils/file'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
feConfigs
}
from
'@/store/static'
;
import
Loading
from
'@/components/Loading'
;
import
Avatar
from
'@/components/Avatar'
;
const
PayModal
=
dynamic
(()
=>
import
(
'./PayModal'
),
{
loading
:
()
=>
<
Loading
fixed=
{
false
}
/>,
ssr
:
false
});
const
UserInfo
=
()
=>
{
const
router
=
useRouter
();
const
{
userInfo
,
updateUserInfo
,
initUserInfo
}
=
useUserStore
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
reset
}
=
useForm
<
UserUpdateParams
>
({
defaultValues
:
userInfo
as
UserType
});
const
{
toast
}
=
useToast
();
const
{
isOpen
:
isOpenPayModal
,
onClose
:
onClosePayModal
,
onOpen
:
onOpenPayModal
}
=
useDisclosure
();
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
fileType
:
'.jpg,.png'
,
multiple
:
false
});
const
onclickSave
=
useCallback
(
async
(
data
:
UserUpdateParams
)
=>
{
setLoading
(
true
);
try
{
await
putUserInfo
({
avatar
:
data
.
avatar
});
updateUserInfo
({
avatar
:
data
.
avatar
});
reset
(
data
);
toast
({
title
:
'更新数据成功'
,
status
:
'success'
});
}
catch
(
error
)
{
toast
({
title
:
getErrText
(
error
),
status
:
'error'
});
}
setLoading
(
false
);
},
[
reset
,
setLoading
,
toast
,
updateUserInfo
]
);
const
onSelectFile
=
useCallback
(
async
(
e
:
File
[])
=>
{
const
file
=
e
[
0
];
if
(
!
file
)
return
;
try
{
const
src
=
await
compressImg
({
file
,
maxW
:
100
,
maxH
:
100
});
onclickSave
({
...
userInfo
,
avatar
:
src
});
}
catch
(
err
:
any
)
{
toast
({
title
:
typeof
err
===
'string'
?
err
:
'头像选择异常'
,
status
:
'warning'
});
}
},
[
onclickSave
,
toast
,
userInfo
]
);
useQuery
([
'init'
],
initUserInfo
,
{
onSuccess
(
res
)
{
reset
(
res
);
}
});
return
(
<
Flex
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
py=
{
[
0
,
8
]
}
fontSize=
{
[
'lg'
,
'xl'
]
}
>
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
w=
{
'260px'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
头像:
</
Box
>
<
Box
flex=
{
1
}
pl=
{
10
}
>
<
Avatar
src=
{
userInfo
?.
avatar
}
w=
{
[
'34px'
,
'44px'
]
}
h=
{
[
'34px'
,
'44px'
]
}
cursor=
{
'pointer'
}
title=
{
'点击切换头像'
}
onClick=
{
onOpenSelectFile
}
/>
</
Box
>
</
Flex
>
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
w=
{
'260px'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
账号:
</
Box
>
<
Box
>
{
userInfo
?.
username
}
</
Box
>
</
Flex
>
{
feConfigs
?.
show_userDetail
&&
(
<
Box
mt=
{
6
}
w=
{
'260px'
}
whiteSpace=
{
'nowrap'
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
余额:
</
Box
>
<
Box
>
<
strong
>
{
userInfo
?.
balance
}
</
strong
>
元
</
Box
>
<
Button
size=
{
[
'xs'
,
'sm'
]
}
w=
{
[
'70px'
,
'80px'
]
}
ml=
{
5
}
onClick=
{
onOpenPayModal
}
>
充值
</
Button
>
</
Flex
>
</
Box
>
)
}
{
isOpenPayModal
&&
<
PayModal
onClose=
{
onClosePayModal
}
/>
}
<
File
onSelect=
{
onSelectFile
}
/>
</
Flex
>
);
};
export
default
UserInfo
;
client/src/pages/number/components/InformTable.tsx
View file @
e0b68607
import
React
from
'react'
;
import
{
Box
,
Flex
,
Accordion
,
AccordionItem
,
AccordionButton
,
AccordionPanel
,
AccordionIcon
}
from
'@chakra-ui/react'
;
import
{
Box
,
Flex
,
useTheme
}
from
'@chakra-ui/react'
;
import
{
getInforms
,
readInform
}
from
'@/api/user'
;
import
{
usePagination
}
from
'@/hooks/usePagination'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
...
...
@@ -16,8 +8,8 @@ import { formatTimeToChatTime } from '@/utils/tools';
import
MyIcon
from
'@/components/Icon'
;
const
BillTable
=
()
=>
{
const
theme
=
useTheme
();
const
{
Loading
}
=
useLoading
();
const
{
data
:
informs
,
isLoading
,
...
...
@@ -31,11 +23,17 @@ const BillTable = () => {
});
return
(
<
Box
mt=
{
2
}
>
<
Accordion
defaultIndex=
{
[
0
,
1
,
2
]
}
allowMultiple
>
<
Flex
flexDirection=
{
'column'
}
py=
{
[
0
,
5
]
}
h=
{
'100%'
}
position=
{
'relative'
}
>
<
Box
px=
{
[
3
,
8
]
}
position=
{
'relative'
}
flex=
{
'1 0 0'
}
h=
{
0
}
overflowY=
{
'auto'
}
>
{
informs
.
map
((
item
)
=>
(
<
AccordionItem
<
Box
key=
{
item
.
_id
}
border=
{
theme
.
borders
.
md
}
py=
{
2
}
px=
{
4
}
borderRadius=
{
'md'
}
cursor=
{
item
.
read
?
'default'
:
'pointer'
}
position=
{
'relative'
}
onClick=
{
async
()
=>
{
if
(
!
item
.
read
)
{
await
readInform
(
item
.
_id
);
...
...
@@ -43,35 +41,31 @@ const BillTable = () => {
}
}
}
>
<
AccordionButton
>
<
Flex
alignItems=
{
'center'
}
flex=
"1"
textAlign=
"left"
>
<
Box
fontWeight=
{
'bold'
}
position=
{
'relative'
}
>
{
!
item
.
read
&&
(
<
Box
w=
{
'5px'
}
h=
{
'5px'
}
borderRadius=
{
'10px'
}
bg=
{
'myRead.600'
}
position=
{
'absolute'
}
top=
{
1
}
left=
{
'-5px'
}
></
Box
>
)
}
{
item
.
title
}
</
Box
>
<
Box
ml=
{
2
}
color=
{
'myGray.500'
}
>
{
formatTimeToChatTime
(
item
.
time
)
}
</
Box
>
</
Flex
>
<
AccordionIcon
/>
</
AccordionButton
>
<
AccordionPanel
pb=
{
4
}
>
{
item
.
content
}
</
AccordionPanel
>
</
AccordionItem
>
<
Flex
alignItems=
{
'center'
}
justifyContent=
{
'space-between'
}
>
<
Box
>
{
item
.
title
}
</
Box
>
<
Box
ml=
{
2
}
color=
{
'myGray.500'
}
>
{
formatTimeToChatTime
(
item
.
time
)
}
</
Box
>
</
Flex
>
<
Box
fontSize=
{
'sm'
}
color=
{
'myGray.600'
}
>
{
item
.
content
}
</
Box
>
{
!
item
.
read
&&
(
<
Box
w=
{
'5px'
}
h=
{
'5px'
}
borderRadius=
{
'10px'
}
bg=
{
'myRead.600'
}
position=
{
'absolute'
}
bottom=
{
'8px'
}
right=
{
'8px'
}
></
Box
>
)
}
</
Box
>
))
}
</
Accordion
>
</
Box
>
{
!
isLoading
&&
informs
.
length
===
0
&&
(
<
Flex
h=
{
'100%'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
pt=
{
'100
px'
}
>
<
Flex
flex=
{
'1 0 0'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
pt=
{
'-48
px'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
暂无通知~
...
...
@@ -79,12 +73,12 @@ const BillTable = () => {
</
Flex
>
)
}
{
total
>
pageSize
&&
(
<
Flex
w=
{
'100%'
}
mt=
{
4
}
justifyContent=
{
'flex-end'
}
>
<
Flex
w=
{
'100%'
}
mt=
{
4
}
px=
{
[
3
,
8
]
}
justifyContent=
{
'flex-end'
}
>
<
Pagination
/>
</
Flex
>
)
}
<
Loading
loading=
{
isLoading
&&
informs
.
length
===
0
}
fixed=
{
false
}
/>
</
Bo
x
>
</
Fle
x
>
);
};
...
...
client/src/pages/number/components/PayRecordTable.tsx
View file @
e0b68607
...
...
@@ -59,45 +59,46 @@ const PayRecordTable = () => {
return
(
<>
<
TableContainer
>
<
Table
>
<
Thead
>
<
Tr
>
<
Th
>
订单号
</
Th
>
<
Th
>
时间
</
Th
>
<
Th
>
金额
</
Th
>
<
Th
>
状态
</
Th
>
<
Th
></
Th
>
</
Tr
>
</
Thead
>
<
Tbody
fontSize=
{
'sm'
}
>
{
payOrders
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
_id
}
>
<
Td
>
{
item
.
orderId
}
</
Td
>
<
Td
>
{
item
.
createTime
?
dayjs
(
item
.
createTime
).
format
(
'YYYY/MM/DD HH:mm:ss'
)
:
'-'
}
</
Td
>
<
Td
>
{
formatPrice
(
item
.
price
)
}
元
</
Td
>
<
Td
>
{
item
.
status
}
</
Td
>
<
Td
>
{
item
.
status
===
'NOTPAY'
&&
(
<
Button
onClick=
{
()
=>
handleRefreshPayOrder
(
item
.
_id
)
}
size=
{
'sm'
}
>
更新
</
Button
>
)
}
</
Td
>
</
Tr
>
))
}
</
Tbody
>
</
Table
>
</
TableContainer
>
{
!
isInitialLoading
&&
payOrders
.
length
===
0
&&
(
<
Flex
h=
{
'100%'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
pt=
{
'100px'
}
>
{
!
isInitialLoading
&&
payOrders
.
length
===
0
?
(
<
Flex
h=
{
'100%'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
无支付记录~
</
Box
>
</
Flex
>
)
:
(
<
TableContainer
py=
{
[
0
,
5
]
}
px=
{
[
3
,
8
]
}
h=
{
'100%'
}
overflow=
{
'overlay'
}
>
<
Table
>
<
Thead
>
<
Tr
>
<
Th
>
订单号
</
Th
>
<
Th
>
时间
</
Th
>
<
Th
>
金额
</
Th
>
<
Th
>
状态
</
Th
>
<
Th
></
Th
>
</
Tr
>
</
Thead
>
<
Tbody
fontSize=
{
'sm'
}
>
{
payOrders
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
_id
}
>
<
Td
>
{
item
.
orderId
}
</
Td
>
<
Td
>
{
item
.
createTime
?
dayjs
(
item
.
createTime
).
format
(
'YYYY/MM/DD HH:mm:ss'
)
:
'-'
}
</
Td
>
<
Td
>
{
formatPrice
(
item
.
price
)
}
元
</
Td
>
<
Td
>
{
item
.
status
}
</
Td
>
<
Td
>
{
item
.
status
===
'NOTPAY'
&&
(
<
Button
onClick=
{
()
=>
handleRefreshPayOrder
(
item
.
_id
)
}
size=
{
'sm'
}
>
更新
</
Button
>
)
}
</
Td
>
</
Tr
>
))
}
</
Tbody
>
</
Table
>
</
TableContainer
>
)
}
<
Loading
loading=
{
isInitialLoading
}
fixed=
{
false
}
/>
</>
...
...
client/src/pages/number/components/PromotionTable.tsx
deleted
100644 → 0
View file @
9fefaa8e
import
React
from
'react'
;
import
{
Flex
,
Table
,
Thead
,
Tbody
,
Tr
,
Th
,
Td
,
TableContainer
,
Box
}
from
'@chakra-ui/react'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
dayjs
from
'dayjs'
;
import
{
getPromotionRecords
}
from
'@/api/user'
;
import
{
usePagination
}
from
'@/hooks/usePagination'
;
import
{
PromotionRecordType
}
from
'@/api/response/user'
;
import
{
PromotionTypeMap
}
from
'@/constants/user'
;
import
MyIcon
from
'@/components/Icon'
;
const
OpenApi
=
()
=>
{
const
{
Loading
}
=
useLoading
();
const
{
data
:
promotionRecords
,
isLoading
,
total
,
pageSize
,
Pagination
}
=
usePagination
<
PromotionRecordType
>
({
api
:
getPromotionRecords
});
return
(
<>
<
TableContainer
position=
{
'relative'
}
overflow=
{
'hidden'
}
minH=
{
'100px'
}
>
<
Table
>
<
Thead
>
<
Tr
>
<
Th
>
时间
</
Th
>
<
Th
>
类型
</
Th
>
<
Th
>
金额
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
fontSize=
{
'sm'
}
>
{
promotionRecords
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
_id
}
>
<
Td
>
{
item
.
createTime
?
dayjs
(
item
.
createTime
).
format
(
'YYYY/MM/DD HH:mm:ss'
)
:
'-'
}
</
Td
>
<
Td
>
{
PromotionTypeMap
[
item
.
type
]
}
</
Td
>
<
Td
>
{
item
.
amount
}
</
Td
>
</
Tr
>
))
}
</
Tbody
>
</
Table
>
</
TableContainer
>
{
!
isLoading
&&
promotionRecords
.
length
===
0
&&
(
<
Flex
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
无佣金记录~
</
Box
>
</
Flex
>
)
}
{
total
>
pageSize
&&
(
<
Flex
mt=
{
4
}
justifyContent=
{
'flex-end'
}
>
<
Pagination
/>
</
Flex
>
)
}
<
Loading
loading=
{
isLoading
}
fixed=
{
false
}
/>
</>
);
};
export
default
OpenApi
;
client/src/pages/number/index.tsx
View file @
e0b68607
import
React
,
{
useCallback
,
useRef
}
from
'react'
;
import
{
Card
,
Box
,
Flex
,
Button
,
Grid
,
useDisclosure
}
from
'@chakra-ui/react'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
UserUpdateParams
}
from
'@/types/user'
;
import
{
putUserInfo
}
from
'@/api/user'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
Box
,
Flex
,
useTheme
}
from
'@chakra-ui/react'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
UserType
}
from
'@/types/user'
;
import
{
clearCookie
}
from
'@/utils/user'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
dynamic
from
'next/dynamic'
;
import
{
useSelectFile
}
from
'@/hooks/useSelectFile'
;
import
{
compressImg
}
from
'@/utils/file'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
feConfigs
}
from
'@/store/static'
;
import
{
clearCookie
}
from
'@/utils/user'
;
import
Loading
from
'@/components/Loading'
;
import
Avatar
from
'@/components/Avatar'
;
import
MyIcon
from
'@/components/Icon'
;
import
Tabs
from
'@/components/Tabs'
;
import
BillTable
from
'./components/BillTable'
;
import
PageContainer
from
'@/components/PageContainer'
;
import
SideTabs
from
'@/components/SideTabs'
;
const
PayRecordTable
=
dynamic
(()
=>
import
(
'./components/PayRecordTable'
),
{
ssr
:
false
})
;
import
Tabs
from
'@/components/Tabs'
;
import
UserInfo
from
'./components/Info'
;
import
{
useUserStore
}
from
'@/store/user'
;
const
InformTable
=
dynamic
(()
=>
import
(
'./components/Inform
Table'
),
{
const
BillTable
=
dynamic
(()
=>
import
(
'./components/Bill
Table'
),
{
ssr
:
false
});
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
),
{
loading
:
()
=>
<
Loading
fixed=
{
false
}
/>,
const
PayRecordTable
=
dynamic
(()
=>
import
(
'./components/PayRecordTable'
),
{
ssr
:
false
});
const
WxConcat
=
dynamic
(()
=>
import
(
'@/components/WxConcat'
),
{
loading
:
()
=>
<
Loading
fixed=
{
false
}
/>,
const
InformTable
=
dynamic
(()
=>
import
(
'./components/InformTable'
),
{
ssr
:
false
});
enum
TableEnum
{
enum
TabEnum
{
'info'
=
'info'
,
'bill'
=
'bill'
,
'pay'
=
'pay'
,
'
promotion'
=
'promotion
'
,
'
inform'
=
'inform
'
'
inform'
=
'inform
'
,
'
loginout'
=
'loginout
'
}
const
NumberSetting
=
({
tableType
}:
{
tableType
:
`
${
TableEnum
}
`
})
=>
{
const
tableList
=
useRef
([
{
label
:
'账单'
,
id
:
TableEnum
.
bill
,
Component
:
<
BillTable
/>
},
{
label
:
'充值'
,
id
:
TableEnum
.
pay
,
Component
:
<
PayRecordTable
/>
},
{
label
:
'通知'
,
id
:
TableEnum
.
inform
,
Component
:
<
InformTable
/>
}
const
NumberSetting
=
({
currentTab
}:
{
currentTab
:
`
${
TabEnum
}
`
})
=>
{
const
tabList
=
useRef
([
{
icon
:
'meLight'
,
label
:
'个人信息'
,
id
:
TabEnum
.
info
,
Component
:
<
BillTable
/>
},
{
icon
:
'billRecordLight'
,
label
:
'消费记录'
,
id
:
TabEnum
.
bill
,
Component
:
<
BillTable
/>
},
{
icon
:
'payRecordLight'
,
label
:
'充值记录'
,
id
:
TabEnum
.
pay
,
Component
:
<
PayRecordTable
/>
},
{
icon
:
'informLight'
,
label
:
'通知'
,
id
:
TabEnum
.
inform
,
Component
:
<
InformTable
/>
},
{
icon
:
'loginoutLight'
,
label
:
'登出'
,
id
:
TabEnum
.
loginout
,
Component
:
()
=>
<></>
}
]);
const
router
=
useRouter
();
const
{
userInfo
,
updateUserInfo
,
initUserInfo
,
setUserInfo
}
=
useUserStore
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
reset
}
=
useForm
<
UserUpdateParams
>
({
defaultValues
:
userInfo
as
UserType
});
const
{
toast
}
=
useToast
();
const
{
isOpen
:
isOpenPayModal
,
onClose
:
onClosePayModal
,
onOpen
:
onOpenPayModal
}
=
useDisclosure
();
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
fileType
:
'.jpg,.png'
,
multiple
:
false
});
const
onclickSave
=
useCallback
(
async
(
data
:
UserUpdateParams
)
=>
{
setLoading
(
true
);
try
{
await
putUserInfo
({
avatar
:
data
.
avatar
});
updateUserInfo
({
avatar
:
data
.
avatar
});
reset
(
data
);
toast
({
title
:
'更新数据成功'
,
status
:
'success'
});
}
catch
(
error
)
{
toast
({
title
:
getErrText
(
error
),
status
:
'error'
});
}
setLoading
(
false
);
},
[
reset
,
setLoading
,
toast
,
updateUserInfo
]
);
const
onSelectFile
=
useCallback
(
async
(
e
:
File
[])
=>
{
const
file
=
e
[
0
];
if
(
!
file
)
return
;
try
{
const
src
=
await
compressImg
({
file
,
maxW
:
100
,
maxH
:
100
});
onclickSave
({
...
userInfo
,
avatar
:
src
});
}
catch
(
err
:
any
)
{
toast
({
title
:
typeof
err
===
'string'
?
err
:
'头像选择异常'
,
status
:
'warning'
const
theme
=
useTheme
();
const
{
isPc
}
=
useGlobalStore
();
const
{
setUserInfo
}
=
useUserStore
();
const
setCurrentTab
=
useCallback
(
(
tab
:
string
)
=>
{
if
(
tab
===
TabEnum
.
loginout
)
{
clearCookie
();
setUserInfo
(
null
);
router
.
replace
(
'/login'
);
}
else
{
router
.
replace
({
query
:
{
currentTab
:
tab
}
});
}
},
[
onclickSave
,
toast
,
u
serInfo
]
[
router
,
setU
serInfo
]
);
const
onclickLogOut
=
useCallback
(()
=>
{
clearCookie
();
setUserInfo
(
null
);
router
.
replace
(
'/login'
);
},
[
router
,
setUserInfo
]);
useQuery
([
'init'
],
initUserInfo
,
{
onSuccess
(
res
)
{
reset
(
res
);
}
});
return
(
<
Box
h=
{
'100%'
}
overflow=
{
'overlay'
}
>
<
Box
py=
{
[
5
,
10
]
}
px=
{
'5vw'
}
>
<
Grid
gridTemplateColumns=
{
[
'1fr'
,
'3fr 300px'
]
}
gridGap=
{
4
}
>
<
Card
px=
{
6
}
py=
{
4
}
>
<
Flex
justifyContent=
{
'space-between'
}
>
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
账号信息
</
Box
>
<
Button
variant=
{
'base'
}
size=
{
'xs'
}
onClick=
{
onclickLogOut
}
>
退出登录
</
Button
>
</
Flex
>
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
头像:
</
Box
>
<
Avatar
src=
{
userInfo
?.
avatar
}
w=
{
[
'28px'
,
'36px'
]
}
h=
{
[
'28px'
,
'36px'
]
}
cursor=
{
'pointer'
}
title=
{
'点击切换头像'
}
onClick=
{
onOpenSelectFile
}
/>
</
Flex
>
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
账号:
</
Box
>
<
Box
>
{
userInfo
?.
username
}
</
Box
>
</
Flex
>
{
feConfigs
?.
show_userDetail
&&
(
<
Box
mt=
{
6
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Box
flex=
{
'0 0 50px'
}
>
余额:
</
Box
>
<
Box
>
<
strong
>
{
userInfo
?.
balance
}
</
strong
>
元
</
Box
>
<
Button
size=
{
[
'xs'
,
'sm'
]
}
w=
{
[
'70px'
,
'80px'
]
}
ml=
{
5
}
onClick=
{
onOpenPayModal
}
>
充值
</
Button
>
</
Flex
>
</
Box
>
)
}
</
Card
>
</
Grid
>
{
feConfigs
?.
show_userDetail
&&
(
<
Card
mt=
{
4
}
px=
{
[
3
,
6
]
}
py=
{
4
}
>
<
PageContainer
>
<
Flex
flexDirection=
{
[
'column'
,
'row'
]
}
h=
{
'100%'
}
pt=
{
[
4
,
0
]
}
>
{
isPc
?
(
<
Flex
flexDirection=
{
'column'
}
p=
{
4
}
h=
{
'100%'
}
flex=
{
'0 0 200px'
}
borderRight=
{
theme
.
borders
.
base
}
>
<
SideTabs
flex=
{
1
}
mx=
{
'auto'
}
mt=
{
2
}
w=
{
'100%'
}
list=
{
tabList
.
current
}
activeId=
{
currentTab
}
onChange=
{
setCurrentTab
}
/>
</
Flex
>
)
:
(
<
Box
mb=
{
3
}
>
<
Tabs
m=
{
'auto'
}
w=
{
'200px'
}
list=
{
tableList
.
current
}
activeId=
{
tableType
}
size=
{
'sm'
}
onChange=
{
(
id
:
any
)
=>
router
.
replace
(
`/number?type=${id}`
)
}
w=
{
'90%'
}
size=
{
isPc
?
'md'
:
'sm'
}
list=
{
tabList
.
current
.
map
((
item
)
=>
({
id
:
item
.
id
,
label
:
item
.
label
}))
}
activeId=
{
currentTab
}
onChange=
{
setCurrentTab
}
/>
<
Box
minH=
{
'300px'
}
>
{
(()
=>
{
const
item
=
tableList
.
current
.
find
((
item
)
=>
item
.
id
===
tableType
);
return
item
?
item
.
Component
:
null
;
})()
}
</
Box
>
</
Card
>
</
Box
>
)
}
</
Box
>
{
isOpenPayModal
&&
<
PayModal
onClose=
{
onClosePayModal
}
/>
}
<
File
onSelect=
{
onSelectFile
}
/>
</
Box
>
<
Box
flex=
{
'1 0 0'
}
h=
{
'100%'
}
pb=
{
[
4
,
0
]
}
>
{
currentTab
===
TabEnum
.
info
&&
<
UserInfo
/>
}
{
currentTab
===
TabEnum
.
bill
&&
<
BillTable
/>
}
{
currentTab
===
TabEnum
.
pay
&&
<
PayRecordTable
/>
}
{
currentTab
===
TabEnum
.
inform
&&
<
InformTable
/>
}
</
Box
>
</
Flex
>
</
PageContainer
>
);
};
export
async
function
getServerSideProps
({
query
}:
any
)
{
return
{
props
:
{
tableType
:
query
?.
type
||
TableEnum
.
bill
currentTab
:
query
?.
currentTab
||
TabEnum
.
info
}
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment