Skip to content

Commit

Permalink
feat: 新增会员和超级会员功能
Browse files Browse the repository at this point in the history
  • Loading branch information
79E committed May 26, 2023
1 parent 8ea432d commit e659c8a
Show file tree
Hide file tree
Showing 16 changed files with 1,020 additions and 744 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "chatgpt-web",
"private": false,
"version": "1.1.1",
"version": "1.2.0",
"description": "ChatGPT Web",
"author": "79E",
"keywords": [
Expand Down
55 changes: 27 additions & 28 deletions src/components/GoodsList/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
flex-wrap: wrap;
gap: 10px;
&_item{
width: 130px;
min-height: 114px;
flex: 1;
min-width: 150px;
min-height: 11px;
box-sizing: content-box;
background-color: #fff;
border-radius: 8px;
padding-top: 30px;
padding: 20px 20px;
display: flex;
flex-direction: column;
align-items: center;
// align-items: center;
border: 2px solid transparent;
border-bottom-width: 0;
transition: border-color 0.4s ease-in-out;
cursor: pointer;
position: relative;
Expand All @@ -26,7 +27,7 @@
}

h3 {
font-size: 22px;
font-size: 24px;
color: #1877ff;
}

Expand All @@ -41,29 +42,27 @@
padding: 2px 6px;
}

&_button{
margin-top: auto;
width: 130px;
height: 32px;
line-height: 30px;
font-size: 16px;
font-weight: 500;
text-align: center;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
background-color: #1677ff;
p{
border-radius: 20px;
background-color: transparent;
font-size: 22px;
color: #FFF;
&_level{
color: #f4c17a;
font-weight: 500;
font-size: 14px;
}

&_price{
display: flex;
align-items: flex-end;
.sales_price{
font-size: 16px;
font-weight: 500;
span{
position: relative;
top: -1px;
font-size: 12px;
}
color: #333;
}
}
.original_price{
font-size: 12px;
color: #999;
text-decoration: line-through;
margin-bottom: 2px;
margin-left: 4px;
}
}
}
}
13 changes: 6 additions & 7 deletions src/components/GoodsList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ function GoodsList(props: { list: Array<ProductInfo>; onChange: (item: ProductIn
setSelectItem(item)
}}
>
{item.integral ? <h3>{item.integral}积分</h3> : <h3>会员{item.day}</h3>}
<div className={styles.goodsList_item_button}>
<p>
{(item.price / 100).toFixed(2)}
<span></span>
</p>
</div>
<p className={styles.goodsList_item_level}>{ item.level === 1 ? '会员' : item.level === 2 ? '超级会员' : '超级特惠' }</p>
{item.type === 'integral' ? <h3>{item.value}积分</h3> : <h3>{item.value}</h3>}
<div className={styles.goodsList_item_price}>
<p className={styles.sales_price}>{(item.price / 100).toFixed(2)}<span></span></p>
{item.original_price && <p className={styles.original_price}>¥{(item.original_price / 100).toFixed(2)}</p>}
</div>
<span className={styles.goodsList_item_tag}>{item.badge}</span>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/components/LoginModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function LoginCard(props: {
]}
onGetCaptcha={async () => {
const account = props.form.getFieldValue('account')
if (!account || !/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(account)) {
if (!account || !/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(account)) {
props.form.setFields([
{
name: 'account',
Expand Down
16 changes: 12 additions & 4 deletions src/components/UserInfoCard/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@
}
&_info{
margin-left: 12px;
p{
font-size: 18px;
font-weight: 500;
&_title{
display: flex;
span{
font-size: 20px;
font-weight: 500;
}
img{
cursor: pointer;
margin-left: 8px;
width: 22px;
}
}
span{
&_account{
font-size: 14px;
color: #555;
}
Expand Down
41 changes: 32 additions & 9 deletions src/components/UserInfoCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import { UserInfo } from '@/types'
import styles from './index.module.less'
import { Space, Statistic } from 'antd'
import { Space, Statistic, Tooltip } from 'antd'
import { useMemo } from 'react'

function UserInfoCard(props: { info?: UserInfo }) {
const subscribe = useMemo(() => {
if (!props.info?.subscribe) return 0

const vipIcon = {
vip: 'https://s.ibaotu.com/next/img/new/ep.4814.png',
svip: 'https://s.ibaotu.com/next/img/new/person.b254.png'
}

const vipDay = useMemo(() => {
if (!props.info?.vip_expire_time) return 0
const today = new Date()
today.setHours(0, 0, 0, 0)
const todayTime = today.getTime()
const subscribeTime = new Date(props.info?.subscribe || 0).getTime()
if (subscribeTime < todayTime) return 0
const time = Math.ceil((subscribeTime - todayTime) / 86400000)
const vipExpireTime = new Date(props.info?.vip_expire_time || 0).getTime()
if (vipExpireTime < todayTime) return 0
const time = Math.ceil((vipExpireTime - todayTime) / 86400000)
return time
}, [props])

const isSvip = useMemo(()=>{
if (!props.info?.svip_expire_time) return 0
const today = new Date()
today.setHours(0, 0, 0, 0)
const todayTime = today.getTime()
const svipExpireTime = new Date(props.info?.svip_expire_time || 0).getTime()
if (svipExpireTime < todayTime) return 0
const time = Math.ceil((svipExpireTime - todayTime) / 86400000)
return time
},[props])

const info = useMemo(() => {
return props.info
}, [props])
Expand All @@ -23,13 +40,19 @@ function UserInfoCard(props: { info?: UserInfo }) {
<div className={styles.userInfo}>
<img className={styles.userInfo_avatar} src={info?.avatar} alt="" />
<div className={styles.userInfo_info}>
<p>{info?.nickname}</p>
<span>{info?.account}</span>
<div className={styles.userInfo_info_title}>
<span>{info?.nickname}</span>
{
isSvip ? <Tooltip title="超级会员"><img src={vipIcon.svip} alt="" /></Tooltip> :
vipDay ? <Tooltip title="会员"><img src={vipIcon.vip} alt="" /></Tooltip>: ''
}
</div>
<span className={styles.userInfo_info_account}>{info?.account}</span>
</div>
<div className={styles.userInfo_vip}>
<Space wrap size="large">
<Statistic title="积分" value={info?.integral} />
<Statistic title="会员(天)" value={subscribe} />
<Statistic title="会员(天)" value={vipDay} />
</Space>
</div>
</div>
Expand Down
70 changes: 52 additions & 18 deletions src/pages/admin/carmi/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function CarmiPage() {
quantity: 1,
reward: 10,
loading: false,
level: 1,
result: ''
})

Expand Down Expand Up @@ -57,6 +58,19 @@ function CarmiPage() {
)
}
},
{
title: '级别',
dataIndex: 'level',
render: (_, data) => {
if (data.level === 1) {
return <Tag color="#f50">普通会员</Tag>
}
if (data.level === 2) {
return <Tag color="#ce9e4f">超级会员</Tag>
}
return <Tag>暂无级别</Tag>
}
},
{
title: '有效期',
dataIndex: 'end_time'
Expand Down Expand Up @@ -167,6 +181,7 @@ function CarmiPage() {
quantity: 1,
loading: false,
reward: 10,
level: 1,
result: ''
})
}}
Expand Down Expand Up @@ -222,23 +237,41 @@ function CarmiPage() {
/>
</div>
</Space>
<div className={styles.formCard}>
<p className={styles.formCard_title}>生成数量</p>
<InputNumber
style={{
width: '100%'
}}
size="large"
min={1}
max={50}
onChange={(e) => {
if (e) {
setGenerateModal(g => ({ ...g, quantity: e }))
}
}}
value={generateModal.quantity}
/>
</div>
<Space
size="large"
>
<div className={styles.formCard}>
<p className={styles.formCard_title}>卡密会员等级</p>
<Radio.Group
size="large"
onChange={(e) => {
setGenerateModal(g => ({ ...g, level: e.target.value }))
}}
defaultValue={generateModal.level}
value={generateModal.level}
>
<Radio.Button value={1}>普通会员</Radio.Button>
<Radio.Button value={2}>超级会员</Radio.Button>
</Radio.Group>
</div>
<div className={styles.formCard}>
<p className={styles.formCard_title}>
生成数量
</p>
<InputNumber
style={{width:'100%'}}
size="large"
min={1}
max={50}
onChange={(e) => {
if (e) {
setGenerateModal(g => ({ ...g, quantity: e }))
}
}}
value={generateModal.quantity}
/>
</div>
</Space>
<div className={styles.generate}
style={{
height: generateModal.result || generateModal.loading ? 120 : 0
Expand Down Expand Up @@ -268,7 +301,8 @@ function CarmiPage() {
type: generateModal.type,
end_time: generateModal.end_time,
quantity: generateModal.quantity,
reward: generateModal.reward
reward: generateModal.reward,
level: generateModal.level
}).then((res) => {
if (res.code) return;
const keys = res.data.map(info => `${info.key}`).join('\n')
Expand Down
8 changes: 6 additions & 2 deletions src/pages/admin/config/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
background-color: #fbfbfb;
h3{
color: #333;
margin-bottom: 12px;
}
p{
margin-top: 4px;
color: #999;
font-size: 14px;
}
}
}
}
Loading

0 comments on commit e659c8a

Please sign in to comment.