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
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
268 additions
and
303 deletions
+268
-303
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
+26
-32
client/src/pages/number/components/PayRecordTable.tsx
+9
-8
client/src/pages/number/components/PromotionTable.tsx
+0
-67
client/src/pages/number/index.tsx
+72
-166
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 = {
...
@@ -63,7 +63,11 @@ const map = {
qaImport
:
require
(
'./icons/file/qaImport.svg'
).
default
,
qaImport
:
require
(
'./icons/file/qaImport.svg'
).
default
,
uploadFile
:
require
(
'./icons/file/uploadFile.svg'
).
default
,
uploadFile
:
require
(
'./icons/file/uploadFile.svg'
).
default
,
closeLight
:
require
(
'./icons/light/close.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
;
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';
...
@@ -6,8 +6,8 @@ import { useForm } from 'react-hook-form';
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
useScreen
}
from
'@/hooks/useScreen'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
type
ComponentRef
}
from
'./components/Info'
;
import
{
type
ComponentRef
}
from
'./components/Info'
;
import
Tabs
from
'@/components/Tabs'
;
import
Tabs
from
'@/components/Tabs'
;
import
dynamic
from
'next/dynamic'
;
import
dynamic
from
'next/dynamic'
;
...
@@ -37,7 +37,7 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
...
@@ -37,7 +37,7 @@ const Detail = ({ kbId, currentTab }: { kbId: string; currentTab: `${TabEnum}` }
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
router
=
useRouter
();
const
{
isPc
}
=
use
Screen
();
const
{
isPc
}
=
use
GlobalStore
();
const
{
kbDetail
,
getKbDetail
}
=
useUserStore
();
const
{
kbDetail
,
getKbDetail
}
=
useUserStore
();
const
tabList
=
useRef
([
const
tabList
=
useRef
([
...
...
client/src/pages/number/components/BillTable.tsx
View file @
e0b68607
...
@@ -21,6 +21,7 @@ import MyIcon from '@/components/Icon';
...
@@ -21,6 +21,7 @@ import MyIcon from '@/components/Icon';
import
DateRangePicker
,
{
type
DateRangeType
}
from
'@/components/DateRangePicker'
;
import
DateRangePicker
,
{
type
DateRangeType
}
from
'@/components/DateRangePicker'
;
import
{
addDays
}
from
'date-fns'
;
import
{
addDays
}
from
'date-fns'
;
import
dynamic
from
'next/dynamic'
;
import
dynamic
from
'next/dynamic'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
const
BillDetail
=
dynamic
(()
=>
import
(
'./BillDetail'
));
const
BillDetail
=
dynamic
(()
=>
import
(
'./BillDetail'
));
...
@@ -30,6 +31,7 @@ const BillTable = () => {
...
@@ -30,6 +31,7 @@ const BillTable = () => {
from
:
addDays
(
new
Date
(),
-
7
),
from
:
addDays
(
new
Date
(),
-
7
),
to
:
new
Date
()
to
:
new
Date
()
});
});
const
{
isPc
}
=
useGlobalStore
();
const
{
const
{
data
:
bills
,
data
:
bills
,
...
@@ -38,6 +40,7 @@ const BillTable = () => {
...
@@ -38,6 +40,7 @@ const BillTable = () => {
getData
getData
}
=
usePagination
<
UserBillType
>
({
}
=
usePagination
<
UserBillType
>
({
api
:
getUserBills
,
api
:
getUserBills
,
pageSize
:
isPc
?
20
:
10
,
params
:
{
params
:
{
dateStart
:
new
Date
(
dateRange
.
from
||
new
Date
()).
setHours
(
0
,
0
,
0
,
0
),
dateStart
:
new
Date
(
dateRange
.
from
||
new
Date
()).
setHours
(
0
,
0
,
0
,
0
),
dateEnd
:
new
Date
(
dateRange
.
to
||
new
Date
()).
setHours
(
23
,
59
,
59
,
999
)
dateEnd
:
new
Date
(
dateRange
.
to
||
new
Date
()).
setHours
(
23
,
59
,
59
,
999
)
...
@@ -47,8 +50,8 @@ const BillTable = () => {
...
@@ -47,8 +50,8 @@ const BillTable = () => {
const
[
billDetail
,
setBillDetail
]
=
useState
<
UserBillType
>
();
const
[
billDetail
,
setBillDetail
]
=
useState
<
UserBillType
>
();
return
(
return
(
<>
<
Flex
flexDirection=
{
'column'
}
py=
{
[
0
,
5
]
}
h=
{
'100%'
}
position=
{
'relative'
}
>
<
TableContainer
p
osition=
{
'relative'
}
minH=
{
'100px
'
}
>
<
TableContainer
p
x=
{
[
3
,
8
]
}
position=
{
'relative'
}
flex=
{
'1 0 0'
}
h=
{
0
}
overflowY=
{
'auto
'
}
>
<
Table
>
<
Table
>
<
Thead
>
<
Thead
>
<
Tr
>
<
Tr
>
...
@@ -78,27 +81,27 @@ const BillTable = () => {
...
@@ -78,27 +81,27 @@ const BillTable = () => {
</
TableContainer
>
</
TableContainer
>
{
!
isLoading
&&
bills
.
length
===
0
&&
(
{
!
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'
}
/>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
无使用记录~
无使用记录~
</
Box
>
</
Box
>
</
Flex
>
</
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
<
DateRangePicker
defaultDate=
{
dateRange
}
defaultDate=
{
dateRange
}
position=
"top"
position=
"top"
onChange=
{
setDateRange
}
onChange=
{
setDateRange
}
onSuccess=
{
()
=>
getData
(
1
)
}
onSuccess=
{
()
=>
getData
(
1
)
}
/>
/>
<
Box
ml=
{
[
0
,
2
]
}
mt=
{
[
3
,
0
]
}
w=
{
[
'100%'
,
'auto'
]
}
>
<
Box
ml=
{
3
}
>
<
Pagination
/>
<
Pagination
/>
</
Box
>
</
Box
>
</
Flex
>
</
Flex
>
<
Loading
loading=
{
isLoading
}
fixed=
{
false
}
/>
<
Loading
loading=
{
isLoading
}
fixed=
{
false
}
/>
{
!!
billDetail
&&
<
BillDetail
bill=
{
billDetail
}
onClose=
{
()
=>
setBillDetail
(
undefined
)
}
/>
}
{
!!
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
React
from
'react'
;
import
{
import
{
Box
,
Flex
,
useTheme
}
from
'@chakra-ui/react'
;
Box
,
Flex
,
Accordion
,
AccordionItem
,
AccordionButton
,
AccordionPanel
,
AccordionIcon
}
from
'@chakra-ui/react'
;
import
{
getInforms
,
readInform
}
from
'@/api/user'
;
import
{
getInforms
,
readInform
}
from
'@/api/user'
;
import
{
usePagination
}
from
'@/hooks/usePagination'
;
import
{
usePagination
}
from
'@/hooks/usePagination'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
...
@@ -16,8 +8,8 @@ import { formatTimeToChatTime } from '@/utils/tools';
...
@@ -16,8 +8,8 @@ import { formatTimeToChatTime } from '@/utils/tools';
import
MyIcon
from
'@/components/Icon'
;
import
MyIcon
from
'@/components/Icon'
;
const
BillTable
=
()
=>
{
const
BillTable
=
()
=>
{
const
theme
=
useTheme
();
const
{
Loading
}
=
useLoading
();
const
{
Loading
}
=
useLoading
();
const
{
const
{
data
:
informs
,
data
:
informs
,
isLoading
,
isLoading
,
...
@@ -31,11 +23,17 @@ const BillTable = () => {
...
@@ -31,11 +23,17 @@ const BillTable = () => {
});
});
return
(
return
(
<
Box
mt=
{
2
}
>
<
Flex
flexDirection=
{
'column'
}
py=
{
[
0
,
5
]
}
h=
{
'100%'
}
position=
{
'relative'
}
>
<
Accordion
defaultIndex=
{
[
0
,
1
,
2
]
}
allowMultiple
>
<
Box
px=
{
[
3
,
8
]
}
position=
{
'relative'
}
flex=
{
'1 0 0'
}
h=
{
0
}
overflowY=
{
'auto'
}
>
{
informs
.
map
((
item
)
=>
(
{
informs
.
map
((
item
)
=>
(
<
AccordionItem
<
Box
key=
{
item
.
_id
}
key=
{
item
.
_id
}
border=
{
theme
.
borders
.
md
}
py=
{
2
}
px=
{
4
}
borderRadius=
{
'md'
}
cursor=
{
item
.
read
?
'default'
:
'pointer'
}
position=
{
'relative'
}
onClick=
{
async
()
=>
{
onClick=
{
async
()
=>
{
if
(
!
item
.
read
)
{
if
(
!
item
.
read
)
{
await
readInform
(
item
.
_id
);
await
readInform
(
item
.
_id
);
...
@@ -43,9 +41,15 @@ const BillTable = () => {
...
@@ -43,9 +41,15 @@ const BillTable = () => {
}
}
}
}
}
}
>
>
<
AccordionButton
>
<
Flex
alignItems=
{
'center'
}
justifyContent=
{
'space-between'
}
>
<
Flex
alignItems=
{
'center'
}
flex=
"1"
textAlign=
"left"
>
<
Box
>
{
item
.
title
}
</
Box
>
<
Box
fontWeight=
{
'bold'
}
position=
{
'relative'
}
>
<
Box
ml=
{
2
}
color=
{
'myGray.500'
}
>
{
formatTimeToChatTime
(
item
.
time
)
}
</
Box
>
</
Flex
>
<
Box
fontSize=
{
'sm'
}
color=
{
'myGray.600'
}
>
{
item
.
content
}
</
Box
>
{
!
item
.
read
&&
(
{
!
item
.
read
&&
(
<
Box
<
Box
w=
{
'5px'
}
w=
{
'5px'
}
...
@@ -53,25 +57,15 @@ const BillTable = () => {
...
@@ -53,25 +57,15 @@ const BillTable = () => {
borderRadius=
{
'10px'
}
borderRadius=
{
'10px'
}
bg=
{
'myRead.600'
}
bg=
{
'myRead.600'
}
position=
{
'absolute'
}
position=
{
'absolute'
}
top=
{
1
}
bottom=
{
'8px'
}
left=
{
'-5
px'
}
right=
{
'8
px'
}
></
Box
>
></
Box
>
)
}
)
}
{
item
.
title
}
</
Box
>
</
Box
>
<
Box
ml=
{
2
}
color=
{
'myGray.500'
}
>
{
formatTimeToChatTime
(
item
.
time
)
}
</
Box
>
</
Flex
>
<
AccordionIcon
/>
</
AccordionButton
>
<
AccordionPanel
pb=
{
4
}
>
{
item
.
content
}
</
AccordionPanel
>
</
AccordionItem
>
))
}
))
}
</
Accordion
>
</
Box
>
{
!
isLoading
&&
informs
.
length
===
0
&&
(
{
!
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'
}
/>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
暂无通知~
暂无通知~
...
@@ -79,12 +73,12 @@ const BillTable = () => {
...
@@ -79,12 +73,12 @@ const BillTable = () => {
</
Flex
>
</
Flex
>
)
}
)
}
{
total
>
pageSize
&&
(
{
total
>
pageSize
&&
(
<
Flex
w=
{
'100%'
}
mt=
{
4
}
justifyContent=
{
'flex-end'
}
>
<
Flex
w=
{
'100%'
}
mt=
{
4
}
px=
{
[
3
,
8
]
}
justifyContent=
{
'flex-end'
}
>
<
Pagination
/>
<
Pagination
/>
</
Flex
>
</
Flex
>
)
}
)
}
<
Loading
loading=
{
isLoading
&&
informs
.
length
===
0
}
fixed=
{
false
}
/>
<
Loading
loading=
{
isLoading
&&
informs
.
length
===
0
}
fixed=
{
false
}
/>
</
Bo
x
>
</
Fle
x
>
);
);
};
};
...
...
client/src/pages/number/components/PayRecordTable.tsx
View file @
e0b68607
...
@@ -59,7 +59,15 @@ const PayRecordTable = () => {
...
@@ -59,7 +59,15 @@ const PayRecordTable = () => {
return
(
return
(
<>
<>
<
TableContainer
>
{
!
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
>
<
Table
>
<
Thead
>
<
Thead
>
<
Tr
>
<
Tr
>
...
@@ -91,13 +99,6 @@ const PayRecordTable = () => {
...
@@ -91,13 +99,6 @@ const PayRecordTable = () => {
</
Tbody
>
</
Tbody
>
</
Table
>
</
Table
>
</
TableContainer
>
</
TableContainer
>
{
!
isInitialLoading
&&
payOrders
.
length
===
0
&&
(
<
Flex
h=
{
'100%'
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
pt=
{
'100px'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
无支付记录~
</
Box
>
</
Flex
>
)
}
)
}
<
Loading
loading=
{
isInitialLoading
}
fixed=
{
false
}
/>
<
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
React
,
{
useCallback
,
useRef
}
from
'react'
;
import
{
Card
,
Box
,
Flex
,
Button
,
Grid
,
useDisclosure
}
from
'@chakra-ui/react'
;
import
{
Box
,
Flex
,
useTheme
}
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
{
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
{
useRouter
}
from
'next/router'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
dynamic
from
'next/dynamic'
;
import
dynamic
from
'next/dynamic'
;
import
{
useSelectFile
}
from
'@/hooks/useSelectFile'
;
import
{
clearCookie
}
from
'@/utils/user'
;
import
{
compressImg
}
from
'@/utils/file'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
{
feConfigs
}
from
'@/store/static'
;
import
Loading
from
'@/components/Loading'
;
import
PageContainer
from
'@/components/PageContainer'
;
import
Avatar
from
'@/components/Avatar'
;
import
SideTabs
from
'@/components/SideTabs'
;
import
MyIcon
from
'@/components/Icon'
;
import
Tabs
from
'@/components/Tabs'
;
import
BillTable
from
'./components/BillTable'
;
const
PayRecordTable
=
dynamic
(()
=>
import
(
'./components/PayRecordTable'
),
{
import
Tabs
from
'@/components/Tabs'
;
ssr
:
false
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
ssr
:
false
});
});
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
),
{
const
PayRecordTable
=
dynamic
(()
=>
import
(
'./components/PayRecordTable'
),
{
loading
:
()
=>
<
Loading
fixed=
{
false
}
/>,
ssr
:
false
ssr
:
false
});
});
const
WxConcat
=
dynamic
(()
=>
import
(
'@/components/WxConcat'
),
{
const
InformTable
=
dynamic
(()
=>
import
(
'./components/InformTable'
),
{
loading
:
()
=>
<
Loading
fixed=
{
false
}
/>,
ssr
:
false
ssr
:
false
});
});
enum
TableEnum
{
enum
TabEnum
{
'info'
=
'info'
,
'bill'
=
'bill'
,
'bill'
=
'bill'
,
'pay'
=
'pay'
,
'pay'
=
'pay'
,
'
promotion'
=
'promotion
'
,
'
inform'
=
'inform
'
,
'
inform'
=
'inform
'
'
loginout'
=
'loginout
'
}
}
const
NumberSetting
=
({
tableType
}:
{
tableType
:
`
${
TableEnum
}
`
})
=>
{
const
NumberSetting
=
({
currentTab
}:
{
currentTab
:
`
${
TabEnum
}
`
})
=>
{
const
tableList
=
useRef
([
const
tabList
=
useRef
([
{
label
:
'账单'
,
id
:
TableEnum
.
bill
,
Component
:
<
BillTable
/>
},
{
icon
:
'meLight'
,
label
:
'个人信息'
,
id
:
TabEnum
.
info
,
Component
:
<
BillTable
/>
},
{
label
:
'充值'
,
id
:
TableEnum
.
pay
,
Component
:
<
PayRecordTable
/>
},
{
icon
:
'billRecordLight'
,
label
:
'消费记录'
,
id
:
TabEnum
.
bill
,
Component
:
<
BillTable
/>
},
{
label
:
'通知'
,
id
:
TableEnum
.
inform
,
Component
:
<
InformTable
/>
}
{
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
router
=
useRouter
();
const
{
userInfo
,
updateUserInfo
,
initUserInfo
,
setUserInfo
}
=
useUserStore
();
const
theme
=
useTheme
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
isPc
}
=
useGlobalStore
();
const
{
reset
}
=
useForm
<
UserUpdateParams
>
({
const
{
setUserInfo
}
=
useUserStore
();
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
(
const
setCurrentTab
=
useCallback
(
async
(
e
:
File
[])
=>
{
(
tab
:
string
)
=>
{
const
file
=
e
[
0
];
if
(
tab
===
TabEnum
.
loginout
)
{
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
]
);
const
onclickLogOut
=
useCallback
(()
=>
{
clearCookie
();
clearCookie
();
setUserInfo
(
null
);
setUserInfo
(
null
);
router
.
replace
(
'/login'
);
router
.
replace
(
'/login'
);
},
[
router
,
setUserInfo
]);
}
else
{
router
.
replace
({
useQuery
([
'init'
],
initUserInfo
,
{
query
:
{
onSuccess
(
res
)
{
currentTab
:
tab
reset
(
res
);
}
}
});
});
}
},
[
router
,
setUserInfo
]
);
return
(
return
(
<
Box
h=
{
'100%'
}
overflow=
{
'overlay'
}
>
<
PageContainer
>
<
Box
py=
{
[
5
,
10
]
}
px=
{
'5vw'
}
>
<
Flex
flexDirection=
{
[
'column'
,
'row'
]
}
h=
{
'100%'
}
pt=
{
[
4
,
0
]
}
>
<
Grid
gridTemplateColumns=
{
[
'1fr'
,
'3fr 300px'
]
}
gridGap=
{
4
}
>
{
isPc
?
(
<
Card
px=
{
6
}
py=
{
4
}
>
<
Flex
<
Flex
justifyContent=
{
'space-between'
}
>
flexDirection=
{
'column'
}
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
p=
{
4
}
账号信息
h=
{
'100%'
}
</
Box
>
flex=
{
'0 0 200px'
}
<
Button
variant=
{
'base'
}
size=
{
'xs'
}
onClick=
{
onclickLogOut
}
>
borderRight=
{
theme
.
borders
.
base
}
退出登录
>
</
Button
>
<
SideTabs
</
Flex
>
flex=
{
1
}
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
>
mx=
{
'auto'
}
<
Box
flex=
{
'0 0 50px'
}
>
头像:
</
Box
>
mt=
{
2
}
<
Avatar
w=
{
'100%'
}
src=
{
userInfo
?.
avatar
}
list=
{
tabList
.
current
}
w=
{
[
'28px'
,
'36px'
]
}
activeId=
{
currentTab
}
h=
{
[
'28px'
,
'36px'
]
}
onChange=
{
setCurrentTab
}
cursor=
{
'pointer'
}
title=
{
'点击切换头像'
}
onClick=
{
onOpenSelectFile
}
/>
/>
</
Flex
>
</
Flex
>
<
Flex
mt=
{
6
}
alignItems=
{
'center'
}
>
)
:
(
<
Box
flex=
{
'0 0 50px'
}
>
账号:
</
Box
>
<
Box
mb=
{
3
}
>
<
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
}
>
<
Tabs
<
Tabs
m=
{
'auto'
}
m=
{
'auto'
}
w=
{
'200px'
}
w=
{
'90%'
}
list=
{
tableList
.
current
}
size=
{
isPc
?
'md'
:
'sm'
}
activeId=
{
tableType
}
list=
{
tabList
.
current
.
map
((
item
)
=>
({
size=
{
'sm'
}
id
:
item
.
id
,
onChange=
{
(
id
:
any
)
=>
router
.
replace
(
`/number?type=${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
>
</
Box
>
</
Card
>
)
}
)
}
<
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
>
</
Box
>
{
isOpenPayModal
&&
<
PayModal
onClose=
{
onClosePayModal
}
/>
}
</
Flex
>
<
File
onSelect=
{
onSelectFile
}
/>
</
PageContainer
>
</
Box
>
);
);
};
};
export
async
function
getServerSideProps
({
query
}:
any
)
{
export
async
function
getServerSideProps
({
query
}:
any
)
{
return
{
return
{
props
:
{
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