@ -1,138 +0,0 @@ |
|||||
import React, { useEffect, useState } from "react"; |
|
||||
import "./Activities.scss"; |
|
||||
import back from "./back.svg"; |
|
||||
import clock from "./clock.svg"; |
|
||||
import detail from "./detail.png"; |
|
||||
import { post } from "../../js/helpers/data-helper"; |
|
||||
|
|
||||
const Activities = ({ |
|
||||
initActivity, |
|
||||
setInitActivity, |
|
||||
onGo, |
|
||||
mall: { activities, pois }, |
|
||||
facilities, |
|
||||
memberID, |
|
||||
}) => { |
|
||||
const [activity, setActivity] = useState(null); |
|
||||
const [receiving, setReceiving] = useState(false); |
|
||||
const poiMap = pois.reduce((acc, nxt) => ({ ...acc, [nxt.code]: nxt }), {}); |
|
||||
const getFacByAct = (activity) => { |
|
||||
if (!activity) return null; |
|
||||
const poiCode = activity.poiList.find((code) => poiMap[code]); |
|
||||
const poi = poiCode ? poiMap[poiCode] : null; |
|
||||
if (!poi) return null; |
|
||||
const actFacs = facilities ? facilities["活动"] : []; |
|
||||
if (!actFacs) return null; |
|
||||
const actFac = actFacs.find(({ title }) => title === poi.name); |
|
||||
return actFac; |
|
||||
}; |
|
||||
|
|
||||
const reject = () => { |
|
||||
window.weui.toast("该活动即将上线,敬请期待!", { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
}; |
|
||||
const receive = async (activity) => { |
|
||||
setReceiving(true); |
|
||||
try { |
|
||||
const { code, data, msg } = await post("/Api/Coupon/CouponReceive", { |
|
||||
activityCode: activity.code, |
|
||||
memberID, |
|
||||
}); |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
activity.isReceived = true; |
|
||||
} |
|
||||
} catch (error) { |
|
||||
console.warn(error); |
|
||||
} finally { |
|
||||
setReceiving(false); |
|
||||
} |
|
||||
}; |
|
||||
useEffect(() => { |
|
||||
if (initActivity) { |
|
||||
setActivity(initActivity); |
|
||||
setInitActivity(null); |
|
||||
} |
|
||||
}, [initActivity]); |
|
||||
|
|
||||
return ( |
|
||||
<div className="activities"> |
|
||||
<div className="header">活动</div> |
|
||||
<div className="list-container"> |
|
||||
{activities && |
|
||||
activities.map((act) => ( |
|
||||
<div key={act.code} className="card"> |
|
||||
<img className="card-header" src={act.fileUrl}></img> |
|
||||
<div className="card-content"> |
|
||||
<div className="detail" onClick={() => setActivity(act)}> |
|
||||
<img src={detail}></img>查看详情 |
|
||||
</div> |
|
||||
<div |
|
||||
className="btn" |
|
||||
onClick={() => { |
|
||||
const fac = getFacByAct(act); |
|
||||
if (!fac) return reject(); |
|
||||
return onGo && onGo(fac); |
|
||||
}} |
|
||||
> |
|
||||
GO |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
))} |
|
||||
</div> |
|
||||
{activity && ( |
|
||||
<div className="activity"> |
|
||||
<img |
|
||||
className="back" |
|
||||
onClick={() => setActivity(null)} |
|
||||
src={back} |
|
||||
></img> |
|
||||
<img className="r1" src={activity.fileUrl}></img> |
|
||||
<div className="r2"> |
|
||||
<div className="rr1">{activity.name}</div> |
|
||||
<div className="rr2"> |
|
||||
<img src={clock}></img> |
|
||||
{activity.beginTime.split(" ")[0]}至 |
|
||||
{activity.endTime.split(" ")[0]} |
|
||||
</div> |
|
||||
<div className="r3"> |
|
||||
<div className="title">活动介绍</div> |
|
||||
{activity.intro} |
|
||||
<div |
|
||||
className="r4" |
|
||||
onClick={() => { |
|
||||
const fac = getFacByAct(activity); |
|
||||
if (!fac) return reject(); |
|
||||
return onGo && onGo(fac); |
|
||||
}} |
|
||||
> |
|
||||
开始导航 |
|
||||
</div> |
|
||||
{activity.defaultAwardTitle && ( |
|
||||
<div className="r5"> |
|
||||
<div className="t1">{activity.defaultAwardTitle}</div> |
|
||||
<div className="meta">活动奖励</div> |
|
||||
<div |
|
||||
onClick={() => |
|
||||
!activity.isReceived && !receiving && receive(activity) |
|
||||
} |
|
||||
className={`btn ${ |
|
||||
activity.isReceived || receiving ? "disabled" : "" |
|
||||
}`}
|
|
||||
> |
|
||||
领取奖励 |
|
||||
</div> |
|
||||
</div> |
|
||||
)} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
)} |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
export default Activities; |
|
||||
@ -1,264 +0,0 @@ |
|||||
.activities { |
|
||||
position: absolute; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
background: #f0f0f0; |
|
||||
|
|
||||
pointer-events: auto; |
|
||||
.header { |
|
||||
position: absolute; |
|
||||
height: 25px; |
|
||||
left: 24px; |
|
||||
top: 24px; |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 18px; |
|
||||
line-height: 25px; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
color: #353230; |
|
||||
} |
|
||||
.list-container { |
|
||||
position: absolute; |
|
||||
top: 64px; |
|
||||
left: 17px; |
|
||||
right: 17px; |
|
||||
bottom: 0; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: auto; |
|
||||
.card { |
|
||||
display: inline-flex; |
|
||||
flex-direction: column; |
|
||||
background: #ffffff; |
|
||||
border-radius: 10px; |
|
||||
overflow: hidden; |
|
||||
.card-header { |
|
||||
width: calc(100vw - 34px); |
|
||||
height: calc((100vw - 34px) / 321 * 180); |
|
||||
border-radius: 10px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
.card-content { |
|
||||
display: flex; |
|
||||
height: 72px; |
|
||||
padding-left: 24px; |
|
||||
padding-right: 16px; |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
color: #353230; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
.detail { |
|
||||
display: inline-flex; |
|
||||
align-items: center; |
|
||||
img { |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
} |
|
||||
.btn { |
|
||||
display: flex; |
|
||||
width: 80px; |
|
||||
height: 40px; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
border-radius: 8px; |
|
||||
font-family: "HarmonyOS Sans SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
line-height: 19px; |
|
||||
text-align: right; |
|
||||
color: #ffffff; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.card + .card { |
|
||||
margin-top: 16px; |
|
||||
} |
|
||||
} |
|
||||
.activity { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: -98px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
background: #f0f0f0; |
|
||||
z-index: 1; |
|
||||
border-radius: 18px; |
|
||||
.back { |
|
||||
position: absolute; |
|
||||
width: 40px; |
|
||||
height: 40px; |
|
||||
left: 16px; |
|
||||
top: 8px; |
|
||||
z-index: 2; |
|
||||
} |
|
||||
.r1 { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
height: 56vw; |
|
||||
width: 100vw; |
|
||||
z-index: 1; |
|
||||
border-radius: 10px 10px 0 0; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
.r2 { |
|
||||
position: absolute; |
|
||||
top: 192px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
z-index: 2; |
|
||||
background: linear-gradient( |
|
||||
180.18deg, |
|
||||
#ffffff 17.3%, |
|
||||
rgba(255, 255, 255, 0) 99.84% |
|
||||
); |
|
||||
border-radius: 16px 16px 0 0; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
.rr1 { |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
margin-top: 16px; |
|
||||
margin-bottom: 8px; |
|
||||
color: #353230; |
|
||||
padding-left: 24px; |
|
||||
} |
|
||||
.rr2 { |
|
||||
display: inline-flex; |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 400; |
|
||||
font-size: 12px; |
|
||||
line-height: 17px; |
|
||||
color: #68655e; |
|
||||
align-items: center; |
|
||||
padding-left: 24px; |
|
||||
img { |
|
||||
width: 16px; |
|
||||
height: 16px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
} |
|
||||
.r3 { |
|
||||
position: absolute; |
|
||||
top: 97px; |
|
||||
left: 10px; |
|
||||
right: 10px; |
|
||||
bottom: 0; |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
line-height: 22px; |
|
||||
color: #9d988f; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: auto; |
|
||||
background: #f9f9fb; |
|
||||
border-radius: 16px 16px 0px 0px; |
|
||||
padding: 16px 14px; |
|
||||
.title { |
|
||||
font-family: "PingFang SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 14px; |
|
||||
line-height: 20px; |
|
||||
color: #353230; |
|
||||
margin-bottom: 4px; |
|
||||
} |
|
||||
} |
|
||||
.r4 { |
|
||||
display: flex; |
|
||||
position: absolute; |
|
||||
height: 56px; |
|
||||
left: 18px; |
|
||||
right: 18px; |
|
||||
bottom: 56px; |
|
||||
margin: auto; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
border-radius: 16px; |
|
||||
font-family: "HarmonyOS Sans SC"; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
.r5 { |
|
||||
position: absolute; |
|
||||
bottom: 139px; |
|
||||
left: 14px; |
|
||||
right: 14px; |
|
||||
height: 80px; |
|
||||
background: rgba(255, 255, 255, 0.7); |
|
||||
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08); |
|
||||
border-radius: 10px; |
|
||||
.t1 { |
|
||||
position: absolute; |
|
||||
top: 19px; |
|
||||
left: 20px; |
|
||||
font-weight: 600; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #437af7; |
|
||||
width: 174px; |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
.meta { |
|
||||
position: absolute; |
|
||||
top: 45px; |
|
||||
left: 20px; |
|
||||
font-weight: 600; |
|
||||
font-size: 12px; |
|
||||
line-height: 16px; |
|
||||
color: #a1a5b3; |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
display: flex; |
|
||||
width: 80px; |
|
||||
height: 40px; |
|
||||
top: 19px; |
|
||||
right: 12px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08); |
|
||||
border-radius: 10px; |
|
||||
font-weight: 600; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #437af7; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
border: 1px solid rgba(80, 138, 247, 0.6); |
|
||||
&.disabled { |
|
||||
color: #a1a5b3; |
|
||||
border: 1px solid #a1a5b3; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 559 B |
|
Before Width: | Height: | Size: 848 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,102 +0,0 @@ |
|||||
import "./ApplyModal.scss"; |
|
||||
import Modal from "react-modal"; |
|
||||
import { useState } from "react"; |
|
||||
import { post } from "../../../js/helpers/data-helper"; |
|
||||
|
|
||||
const ApplyModal = ({ onBack, memberID }) => { |
|
||||
const [title, setTitle] = useState(""); |
|
||||
const [totalCount, setTotalCount] = useState(""); |
|
||||
const [beginTime, setBeginTime] = useState(""); |
|
||||
const [endTime, setEndTime] = useState(""); |
|
||||
const [couponRules, setCouponRules] = useState(""); |
|
||||
const toast = (text) => |
|
||||
window.weui.toast(text, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
const submit = async () => { |
|
||||
if (!title) return toast("请输入礼券标题"); |
|
||||
if (!totalCount) return toast("请输入发放数量"); |
|
||||
if (!beginTime) return toast("请选择开始时间"); |
|
||||
if (!endTime) return toast("请选择结束时间"); |
|
||||
try { |
|
||||
const { code, msg } = await post("/api/coupon/ApplyCoupon", { |
|
||||
title, |
|
||||
totalCount, |
|
||||
beginTime, |
|
||||
endTime, |
|
||||
memberID, |
|
||||
couponRules, |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
toast("已提交申请,审核中!"); |
|
||||
onBack && onBack(); |
|
||||
} else { |
|
||||
toast(msg); |
|
||||
} |
|
||||
} catch (error) {} |
|
||||
}; |
|
||||
return ( |
|
||||
<Modal isOpen ariaHideApp={false} className="ApplyModal"> |
|
||||
<div className="back" onClick={() => onBack && onBack()}></div> |
|
||||
<div className="title">申请发券</div> |
|
||||
<div className="content"> |
|
||||
<div className="item"> |
|
||||
<div className="label">礼券标题</div> |
|
||||
<input |
|
||||
type="text" |
|
||||
className="inputText" |
|
||||
placeholder="请输入礼券标题" |
|
||||
maxLength={30} |
|
||||
value={title} |
|
||||
onChange={(e) => setTitle(e.target.value)} |
|
||||
></input> |
|
||||
</div> |
|
||||
<div className="item"> |
|
||||
<div className="label">发放数量</div> |
|
||||
<input |
|
||||
type="number" |
|
||||
className="inputText" |
|
||||
placeholder="请输入发放数量" |
|
||||
value={totalCount} |
|
||||
min={1} |
|
||||
max={9999} |
|
||||
onChange={(e) => setTotalCount(e.target.value)} |
|
||||
></input> |
|
||||
</div> |
|
||||
<div className="item"> |
|
||||
<div className="label">使用期限</div> |
|
||||
<div className="dates"> |
|
||||
<input |
|
||||
type="date" |
|
||||
value={beginTime} |
|
||||
onChange={(e) => setBeginTime(e.target.value)} |
|
||||
placeholder="请选择开始时间" |
|
||||
></input> |
|
||||
<div style={{ margin: "0 15px" }}>至</div> |
|
||||
<input |
|
||||
type="date" |
|
||||
value={endTime} |
|
||||
onChange={(e) => setEndTime(e.target.value)} |
|
||||
placeholder="请选择结束时间" |
|
||||
></input> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className="item"> |
|
||||
<div className="label">礼券规则</div> |
|
||||
<textarea |
|
||||
type="text" |
|
||||
className="inputTextArea" |
|
||||
placeholder="请输入礼券规则" |
|
||||
value={couponRules} |
|
||||
maxLength={100} |
|
||||
onChange={(e) => setCouponRules(e.target.value)} |
|
||||
></textarea> |
|
||||
</div> |
|
||||
<div className="btn" onClick={submit}> |
|
||||
免费申请 |
|
||||
</div> |
|
||||
</div> |
|
||||
</Modal> |
|
||||
); |
|
||||
}; |
|
||||
export default ApplyModal; |
|
||||
@ -1,118 +0,0 @@ |
|||||
.ApplyModal { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
background: #f6f6f6; |
|
||||
overflow: hidden; |
|
||||
.back { |
|
||||
position: absolute; |
|
||||
top: 10px; |
|
||||
left: 10px; |
|
||||
width: 60px; |
|
||||
height: 60px; |
|
||||
background: center / cover no-repeat url(./back.svg); |
|
||||
} |
|
||||
.title { |
|
||||
position: absolute; |
|
||||
top: 28px; |
|
||||
right: 16px; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 20px; |
|
||||
line-height: 25px; |
|
||||
color: #000000; |
|
||||
} |
|
||||
.content { |
|
||||
position: absolute; |
|
||||
top: 92px; |
|
||||
left: 10px; |
|
||||
right: 10px; |
|
||||
bottom: 34px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 18px; |
|
||||
padding: 32px 24px; |
|
||||
.item { |
|
||||
height: 58px; |
|
||||
border-bottom: 1px solid rgba(218, 215, 209, 0.4); |
|
||||
.label { |
|
||||
font-weight: 600; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #353230; |
|
||||
margin-bottom: 8px; |
|
||||
} |
|
||||
.inputText { |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #68655e; |
|
||||
border: none; |
|
||||
outline: none; |
|
||||
opacity: 0.8; |
|
||||
&::placeholder { |
|
||||
color: #dad7d1; |
|
||||
} |
|
||||
} |
|
||||
.inputTextArea { |
|
||||
width: 100%; |
|
||||
background: #f9f9fb; |
|
||||
border-radius: 8px; |
|
||||
height: 152px; |
|
||||
padding: 16px; |
|
||||
border: none; |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
outline: none; |
|
||||
color: #68655e; |
|
||||
&::placeholder { |
|
||||
color: #dad7d1; |
|
||||
} |
|
||||
} |
|
||||
.dates { |
|
||||
display: flex; |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #353230; |
|
||||
|
|
||||
input { |
|
||||
flex: 1; |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #68655e; |
|
||||
border: none; |
|
||||
outline: none; |
|
||||
opacity: 0.8; |
|
||||
overflow: hidden; |
|
||||
&::placeholder { |
|
||||
color: #dad7d1; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.item + .item { |
|
||||
margin-top: 24px; |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
left: 18px; |
|
||||
right: 18px; |
|
||||
bottom: 18px; |
|
||||
height: 56px; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
border-radius: 10px; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
color: #ffffff; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 544 B |
@ -1,163 +0,0 @@ |
|||||
import "./CouponList.scss"; |
|
||||
import { useState, useRef, useEffect, useCallback } from "react"; |
|
||||
import ListEnd from "../ListEnd/ListEnd"; |
|
||||
import noData from "./noData.png"; |
|
||||
import Qrcode from "../Qrcode/Qrcode"; |
|
||||
import Modal from "react-modal"; |
|
||||
import { post } from "../../../js/helpers/data-helper"; |
|
||||
import InfiniteScroll from "react-infinite-scroller"; |
|
||||
|
|
||||
const stateMap = { |
|
||||
0: "未使用", |
|
||||
1: "已使用", |
|
||||
2: "已失效", |
|
||||
}; |
|
||||
const stateList = [0, 1, 2]; |
|
||||
const CouponList = ({ memberID }) => { |
|
||||
const [state, setState] = useState(stateList[0]); |
|
||||
const [list, setList] = useState([]); |
|
||||
const [nextPageIndex, setNextPageIndex] = useState(1); |
|
||||
const [loading, setLoading] = useState(false); |
|
||||
const hasMore = nextPageIndex !== null; |
|
||||
|
|
||||
const [modalCoupon, setModalCoupon] = useState(null); |
|
||||
const listRef = useRef(); |
|
||||
const showNoData = list !== null && list.length === 0; |
|
||||
const showListEnd = list !== null && list.length > 0; |
|
||||
const showCouponModal = !!modalCoupon; |
|
||||
|
|
||||
const loadMore = useCallback(async () => { |
|
||||
if (loading || nextPageIndex === null || !memberID) return; |
|
||||
setLoading(true); |
|
||||
try { |
|
||||
const { code, data, msg } = await post("/api/coupon/UserCouponList", { |
|
||||
paging: 1, |
|
||||
state, |
|
||||
pageIndex: nextPageIndex, |
|
||||
pageSize: 10, |
|
||||
memberID, |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
setList([...list, ...data.list]); |
|
||||
setNextPageIndex( |
|
||||
nextPageIndex + 1 > data.allPage ? null : nextPageIndex + 1 |
|
||||
); |
|
||||
} else { |
|
||||
setNextPageIndex(null); |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
} |
|
||||
} catch (error) { |
|
||||
setNextPageIndex(null); |
|
||||
} finally { |
|
||||
setLoading(false); |
|
||||
} |
|
||||
}, [list, loading, nextPageIndex]); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (listRef.current) listRef.current.scrollTop = 0; |
|
||||
setNextPageIndex(1); |
|
||||
setList([]); |
|
||||
}, [state]); |
|
||||
|
|
||||
return ( |
|
||||
<div className="CouponList"> |
|
||||
<div className="CouponTabs"> |
|
||||
{stateList.map((item) => ( |
|
||||
<div |
|
||||
key={item} |
|
||||
className={`tab ${state === item ? "active" : ""}`} |
|
||||
onClick={() => setState(item)} |
|
||||
> |
|
||||
{stateMap[item]} |
|
||||
</div> |
|
||||
))} |
|
||||
</div> |
|
||||
<div className="list-container" ref={listRef}> |
|
||||
<InfiniteScroll |
|
||||
pageStart={0} |
|
||||
loadMore={loadMore} |
|
||||
hasMore={hasMore} |
|
||||
useWindow={false} |
|
||||
getScrollParent={() => listRef && listRef.current} |
|
||||
> |
|
||||
{showNoData && ( |
|
||||
<div className="noData"> |
|
||||
<img className="bg" src={noData}></img> |
|
||||
<div className="meta"> |
|
||||
<div className="btn" onClick={() => {}}> |
|
||||
参加AR |
|
||||
</div> |
|
||||
活动,可领取优惠券! |
|
||||
</div> |
|
||||
</div> |
|
||||
)} |
|
||||
{list !== null && |
|
||||
list.map((coupon) => ( |
|
||||
<div |
|
||||
key={coupon.orderNo} |
|
||||
className={`coupon bg${state}`} |
|
||||
onClick={() => setModalCoupon(coupon)} |
|
||||
> |
|
||||
{coupon.logoUrl ? ( |
|
||||
<img |
|
||||
className="logo" |
|
||||
src={coupon.logoUrl} |
|
||||
style={{ |
|
||||
width: (window.innerWidth / 375) * 64, |
|
||||
height: (window.innerWidth / 375) * 64, |
|
||||
}} |
|
||||
></img> |
|
||||
) : ( |
|
||||
<Qrcode |
|
||||
className="qrcode" |
|
||||
size={(window.innerWidth / 375) * 64} |
|
||||
text={coupon.orderNo} |
|
||||
></Qrcode> |
|
||||
)} |
|
||||
<div className="title">{coupon.title}</div> |
|
||||
<div className="meta">{coupon.showNo}</div> |
|
||||
<div className="duration"> |
|
||||
使用期限<div className="sep"></div> |
|
||||
{coupon.beginTime}至{coupon.endTime} |
|
||||
</div> |
|
||||
</div> |
|
||||
))} |
|
||||
|
|
||||
{showListEnd && <ListEnd></ListEnd>} |
|
||||
</InfiniteScroll> |
|
||||
</div> |
|
||||
{showCouponModal && ( |
|
||||
<Modal |
|
||||
isOpen |
|
||||
ariaHideApp={false} |
|
||||
style={{ overlay: { background: "rgba(0, 0, 0, 0.6)" } }} |
|
||||
className="CouponModal" |
|
||||
> |
|
||||
<div className="close" onClick={() => setModalCoupon(null)}></div> |
|
||||
<Qrcode |
|
||||
className="qrcode" |
|
||||
size={120} |
|
||||
text={modalCoupon.orderNo} |
|
||||
></Qrcode> |
|
||||
<div className="content"> |
|
||||
<div className="title">{modalCoupon.title}</div> |
|
||||
<div className="coupon-code">{modalCoupon.showNo}</div> |
|
||||
<div className="meta">使用期限</div> |
|
||||
<div className="value"> |
|
||||
{modalCoupon.beginTime}至{modalCoupon.endTime} |
|
||||
</div> |
|
||||
{modalCoupon.couponRules && ( |
|
||||
<> |
|
||||
<div className="meta">礼券规则</div> |
|
||||
<div className="value">{modalCoupon.couponRules}</div> |
|
||||
</> |
|
||||
)} |
|
||||
</div> |
|
||||
</Modal> |
|
||||
)} |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
export default CouponList; |
|
||||
@ -1,268 +0,0 @@ |
|||||
.CouponList { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
background: linear-gradient( |
|
||||
180deg, |
|
||||
#f2f2f2 0%, |
|
||||
rgba(249, 249, 249, 0) 20.18% |
|
||||
); |
|
||||
border-radius: 18px 18px 0 0; |
|
||||
padding-top: 10px; |
|
||||
width: 100vw; |
|
||||
align-items: center; |
|
||||
overflow: hidden; |
|
||||
.CouponTabs { |
|
||||
display: flex; |
|
||||
flex: 0 0 56px; |
|
||||
width: calc(100vw - 20px); |
|
||||
background: #ffffff; |
|
||||
border-radius: 10px; |
|
||||
|
|
||||
.tab { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
flex: 1; |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #9d988f; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
&.active { |
|
||||
color: #508af7; |
|
||||
&::before { |
|
||||
content: ""; |
|
||||
position: absolute; |
|
||||
bottom: 10px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
width: 4px; |
|
||||
height: 4px; |
|
||||
background: #508af7; |
|
||||
border-radius: 50%; |
|
||||
} |
|
||||
&::after { |
|
||||
content: ""; |
|
||||
position: absolute; |
|
||||
width: 30px; |
|
||||
height: 6px; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
background: center / cover no-repeat url(./tri.svg); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.list-container { |
|
||||
flex: 1; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: scroll; |
|
||||
padding-top: 16px; |
|
||||
text-align: center; |
|
||||
scroll-behavior: smooth; |
|
||||
|
|
||||
&::-webkit-scrollbar { |
|
||||
display: none; |
|
||||
} |
|
||||
.coupon { |
|
||||
position: relative; |
|
||||
width: calc(100vw - 20px); |
|
||||
height: calc((100vw - 20px) / 355 * 134); |
|
||||
&.bg0 { |
|
||||
background: center / cover no-repeat url(./bg0.svg); |
|
||||
} |
|
||||
&.bg1 { |
|
||||
background: center / cover no-repeat url(./bg1.svg); |
|
||||
} |
|
||||
&.bg2 { |
|
||||
background: center / cover no-repeat url(./bg2.svg); |
|
||||
} |
|
||||
.logo { |
|
||||
position: absolute; |
|
||||
top: 5.333vw; |
|
||||
left: 5.333vw; |
|
||||
border-radius: 4px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
.title { |
|
||||
position: absolute; |
|
||||
top: 8vw; |
|
||||
left: 27.733vw; |
|
||||
right: 2.667vw; |
|
||||
font-weight: 600; |
|
||||
font-size: 4.533vw; |
|
||||
line-height: 5.867vw; |
|
||||
color: #353230; |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
text-align: left; |
|
||||
} |
|
||||
.meta { |
|
||||
position: absolute; |
|
||||
top: 14.933vw; |
|
||||
left: 27.733vw; |
|
||||
font-weight: 600; |
|
||||
font-size: 3.467vw; |
|
||||
line-height: 4.8vw; |
|
||||
color: #68655e; |
|
||||
opacity: 0.8; |
|
||||
} |
|
||||
.duration { |
|
||||
position: absolute; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
height: 9.067vw; |
|
||||
font-weight: 400; |
|
||||
font-size: 3.2vw; |
|
||||
line-height: 4.267vw; |
|
||||
text-align: center; |
|
||||
color: #9d988f; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
.sep { |
|
||||
width: 0.267vw; |
|
||||
height: 2.667vw; |
|
||||
opacity: 0.3; |
|
||||
border-left: 0.267vw solid #68655e; |
|
||||
margin-left: 3.2vw; |
|
||||
margin-right: 3.2vw; |
|
||||
} |
|
||||
} |
|
||||
.time-left { |
|
||||
position: absolute; |
|
||||
height: 3.467vw; |
|
||||
top: 2.133vw; |
|
||||
right: 1.067vw; |
|
||||
font-weight: 600; |
|
||||
font-size: 2.933vw; |
|
||||
line-height: 3.467vw; |
|
||||
color: #c1a672; |
|
||||
opacity: 0.8; |
|
||||
} |
|
||||
.qrcode { |
|
||||
position: absolute; |
|
||||
top: 5.333vw; |
|
||||
left: 5.333vw; |
|
||||
} |
|
||||
} |
|
||||
.coupon + .coupon { |
|
||||
margin-top: 8px; |
|
||||
} |
|
||||
.noData { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
width: calc(100vw - 20px); |
|
||||
height: 396px; |
|
||||
border-radius: 18px; |
|
||||
background: #ffffff; |
|
||||
align-items: center; |
|
||||
.bg { |
|
||||
margin: auto; |
|
||||
width: 250px; |
|
||||
height: 250px; |
|
||||
margin-top: 16px; |
|
||||
} |
|
||||
.meta { |
|
||||
width: calc(100vw - 46px); |
|
||||
flex: 0 0 90px; |
|
||||
border-top: 1px solid #f5f5f5; |
|
||||
display: flex; |
|
||||
font-weight: 400; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #9d988f; |
|
||||
height: 90px; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
.btn { |
|
||||
color: #508af7; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.CouponModal { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
width: 326px; |
|
||||
height: 416px; |
|
||||
margin: auto; |
|
||||
background: #f9f9fb; |
|
||||
border-radius: 16px; |
|
||||
.close { |
|
||||
position: absolute; |
|
||||
top: 16px; |
|
||||
right: 16px; |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
background: center / cover no-repeat url(./close.svg); |
|
||||
} |
|
||||
.qrcode { |
|
||||
position: absolute; |
|
||||
top: 52px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
} |
|
||||
.content { |
|
||||
position: absolute; |
|
||||
bottom: 8px; |
|
||||
left: 8px; |
|
||||
right: 8px; |
|
||||
background: #f3f4f8; |
|
||||
border-radius: 10px; |
|
||||
height: 192px; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: flex-start; |
|
||||
flex-direction: column; |
|
||||
padding: 24px 16px 0 16px; |
|
||||
.title { |
|
||||
font-weight: 600; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #323337; |
|
||||
} |
|
||||
.coupon-code { |
|
||||
font-weight: 600; |
|
||||
font-size: 13px; |
|
||||
line-height: 18px; |
|
||||
color: #437af7; |
|
||||
opacity: 0.8; |
|
||||
margin-top: 4px; |
|
||||
padding-bottom: 8px; |
|
||||
border-bottom: 1px dashed #c9cbd1; |
|
||||
margin-bottom: 17px; |
|
||||
width: 100%; |
|
||||
} |
|
||||
.meta { |
|
||||
font-weight: 400; |
|
||||
font-size: 12px; |
|
||||
line-height: 16px; |
|
||||
color: #7a7e8d; |
|
||||
opacity: 0.8; |
|
||||
margin-bottom: 2px; |
|
||||
} |
|
||||
.value { |
|
||||
font-weight: 600; |
|
||||
font-size: 12px; |
|
||||
line-height: 16px; |
|
||||
color: #474a56; |
|
||||
opacity: 0.8; |
|
||||
margin-bottom: 8px; |
|
||||
min-height: 16px; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 313 B |
@ -1,55 +0,0 @@ |
|||||
import "./Coupons.scss"; |
|
||||
import notMember from "./notMember.png"; |
|
||||
import Modal from "react-modal"; |
|
||||
import { useState } from "react"; |
|
||||
import ShopTabs from "./ShopTabs/ShopTabs"; |
|
||||
import CouponList from "./CouponList/CouponList"; |
|
||||
import ShopManager from "./ShopManager/ShopManager"; |
|
||||
|
|
||||
const Coupons = ({ show, memberID, isShop = false }) => { |
|
||||
const isNotMember = !memberID; |
|
||||
const [showCoupons, setShowCoupons] = useState(true); |
|
||||
return ( |
|
||||
<Modal |
|
||||
isOpen={show} |
|
||||
ariaHideApp={false} |
|
||||
style={{ overlay: { background: "transparent", pointerEvents: "none" } }} |
|
||||
className="Coupons" |
|
||||
> |
|
||||
{isNotMember ? ( |
|
||||
<div className="notMember"> |
|
||||
<img className="bg" src={notMember}></img> |
|
||||
<div className="meta"> |
|
||||
<div |
|
||||
className="btn" |
|
||||
onClick={() => { |
|
||||
window.wx.miniProgram.redirectTo({ |
|
||||
url: `/pages/login/index`, |
|
||||
}); |
|
||||
}} |
|
||||
> |
|
||||
注册/登录 |
|
||||
</div> |
|
||||
后,可查看优惠卷 |
|
||||
</div> |
|
||||
</div> |
|
||||
) : ( |
|
||||
<> |
|
||||
{isShop && ( |
|
||||
<ShopTabs |
|
||||
showCoupons={showCoupons} |
|
||||
setShowCoupons={setShowCoupons} |
|
||||
></ShopTabs> |
|
||||
)} |
|
||||
{(!isShop || (isShop && showCoupons)) && ( |
|
||||
<CouponList memberID={memberID}></CouponList> |
|
||||
)} |
|
||||
{isShop && !showCoupons && ( |
|
||||
<ShopManager memberID={memberID}></ShopManager> |
|
||||
)} |
|
||||
</> |
|
||||
)} |
|
||||
</Modal> |
|
||||
); |
|
||||
}; |
|
||||
export default Coupons; |
|
||||
@ -1,69 +0,0 @@ |
|||||
.Coupons { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 98px; |
|
||||
z-index: 100000; |
|
||||
background: #f6f6f6; |
|
||||
pointer-events: auto; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
.notMember { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
width: calc(100vw - 20px); |
|
||||
height: 396px; |
|
||||
border-radius: 18px; |
|
||||
background: #ffffff; |
|
||||
align-items: center; |
|
||||
.bg { |
|
||||
margin: auto; |
|
||||
width: 250px; |
|
||||
height: 250px; |
|
||||
margin-top: 16px; |
|
||||
} |
|
||||
.meta { |
|
||||
width: calc(100vw - 46px); |
|
||||
flex: 0 0 90px; |
|
||||
border-top: 1px solid #f5f5f5; |
|
||||
display: flex; |
|
||||
font-weight: 400; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #9d988f; |
|
||||
height: 90px; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
.btn { |
|
||||
color: #437af7; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.shopTabs { |
|
||||
display: flex; |
|
||||
width: calc(100vw - 20px); |
|
||||
height: 56px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
padding: 4px; |
|
||||
.tab { |
|
||||
display: flex; |
|
||||
flex: 1; |
|
||||
height: 48px; |
|
||||
font-weight: 500; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
color: #68655e; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
border-radius: 8px; |
|
||||
&.active { |
|
||||
color: #ffffff; |
|
||||
background: #daba7f; |
|
||||
box-shadow: 0px 6px 12px rgba(214, 154, 66, 0.3); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,4 +0,0 @@ |
|||||
import bg from "./bg.svg"; |
|
||||
import "./ListEnd.scss"; |
|
||||
const ListEnd = () => <img className="ListEnd" src={bg}></img>; |
|
||||
export default ListEnd; |
|
||||
@ -1,5 +0,0 @@ |
|||||
.ListEnd { |
|
||||
margin-top: 24px; |
|
||||
width: 62px; |
|
||||
height: 40px; |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,25 +0,0 @@ |
|||||
import QRCode from "qrcodejs2"; |
|
||||
import { useRef, useEffect } from "react"; |
|
||||
const Qrcode = ({ size, text, className }) => { |
|
||||
const ref = useRef(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
const domEl = ref.current; |
|
||||
domEl.innerHTML = ""; |
|
||||
new QRCode(domEl, { |
|
||||
width: size, |
|
||||
height: size, |
|
||||
text, |
|
||||
colorDark: "#000", |
|
||||
colorLight: "#fff", |
|
||||
}); |
|
||||
}, [ref]); |
|
||||
return ( |
|
||||
<div |
|
||||
className={className} |
|
||||
ref={ref} |
|
||||
style={{ width: size + "px", height: size + "px" }} |
|
||||
></div> |
|
||||
); |
|
||||
}; |
|
||||
export default Qrcode; |
|
||||
@ -1,59 +0,0 @@ |
|||||
import "./ScanModal.scss"; |
|
||||
import Modal from "react-modal"; |
|
||||
import { useState, useEffect } from "react"; |
|
||||
import { Html5Qrcode } from "html5-qrcode"; |
|
||||
|
|
||||
const ScanModal = ({ onBack, onCode }) => { |
|
||||
const [loaded, setLoaded] = useState(false); |
|
||||
|
|
||||
const toast = (text) => |
|
||||
window.weui.toast(text, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (loaded) { |
|
||||
const dom = document.getElementById("qrcode-scaner"); |
|
||||
const html5QrCode = new Html5Qrcode("qrcode-scaner"); |
|
||||
html5QrCode |
|
||||
.start( |
|
||||
{ facingMode: "environment" }, |
|
||||
{ fps: 10, qrbox: { width: 280, height: 280 } }, |
|
||||
(code) => { |
|
||||
html5QrCode.stop(); |
|
||||
onCode && onCode(code); |
|
||||
} |
|
||||
) |
|
||||
.catch(() => { |
|
||||
toast("启动二维码扫描失败"); |
|
||||
onBack && onBack(); |
|
||||
}); |
|
||||
return () => { |
|
||||
html5QrCode.stop(); |
|
||||
}; |
|
||||
} |
|
||||
}, [loaded]); |
|
||||
return ( |
|
||||
<Modal |
|
||||
onAfterOpen={() => setLoaded(true)} |
|
||||
isOpen |
|
||||
ariaHideApp={false} |
|
||||
className="ScanModal" |
|
||||
> |
|
||||
<div className="border"> |
|
||||
<div className="scaner"></div> |
|
||||
<div |
|
||||
className="container" |
|
||||
id="qrcode-scaner" |
|
||||
width="280px" |
|
||||
height="280px" |
|
||||
></div> |
|
||||
</div> |
|
||||
<div className="btn" onClick={() => onBack && onBack()}> |
|
||||
手动输入券码 |
|
||||
</div> |
|
||||
<div className="back" onClick={() => onBack && onBack()}></div> |
|
||||
</Modal> |
|
||||
); |
|
||||
}; |
|
||||
export default ScanModal; |
|
||||
@ -1,72 +0,0 @@ |
|||||
.ScanModal { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
background: #353230; |
|
||||
overflow: hidden; |
|
||||
.back { |
|
||||
position: absolute; |
|
||||
bottom: 48px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
width: 48px; |
|
||||
height: 48px; |
|
||||
background: center / cover no-repeat url(./close.svg); |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
height: 56px; |
|
||||
left: 29px; |
|
||||
right: 28px; |
|
||||
bottom: 130px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 10px; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
color: #437af7; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
.border { |
|
||||
position: absolute; |
|
||||
top: 94px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
width: 320px; |
|
||||
height: 320px; |
|
||||
background: center / cover no-repeat url(./border.svg); |
|
||||
overflow: hidden; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
@keyframes scaner { |
|
||||
0% { |
|
||||
top: -74px; |
|
||||
} |
|
||||
100% { |
|
||||
top: 320px; |
|
||||
} |
|
||||
} |
|
||||
.scaner { |
|
||||
position: absolute; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
width: 320px; |
|
||||
height: 74px; |
|
||||
background: center / cover no-repeat url(./scaner.svg); |
|
||||
animation: 1s scaner infinite ease-in-out; |
|
||||
z-index: 2; |
|
||||
} |
|
||||
.container { |
|
||||
width: 280px; |
|
||||
height: 280px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 758 B |
|
Before Width: | Height: | Size: 424 B |
@ -1,130 +0,0 @@ |
|||||
import "./ShopManager.scss"; |
|
||||
import noDataPic from "./noDataPic.png"; |
|
||||
import { post } from "../../../js/helpers/data-helper"; |
|
||||
import InfiniteScroll from "react-infinite-scroller"; |
|
||||
import { useState, useRef, useCallback } from "react"; |
|
||||
import ListEnd from "../ListEnd/ListEnd"; |
|
||||
import ApplyModal from "../ApplyModal/ApplyModal"; |
|
||||
import WriteOffModal from "../WriteOffModal/WriteOffModal"; |
|
||||
|
|
||||
const stateMap = { |
|
||||
0: "待审核", |
|
||||
1: "已发布", |
|
||||
2: "已拒绝", |
|
||||
}; |
|
||||
|
|
||||
const ShopManager = ({ memberID }) => { |
|
||||
const [list, setList] = useState([]); |
|
||||
const [nextPageIndex, setNextPageIndex] = useState(1); |
|
||||
const [loading, setLoading] = useState(false); |
|
||||
|
|
||||
const [showApplyModal, setShowApplyModal] = useState(false); |
|
||||
const [showWriteOffModal, setShowWriteOffModal] = useState(false); |
|
||||
const listRef = useRef(); |
|
||||
const showNoData = !loading && list.length === 0; |
|
||||
const showListEnd = !loading && list.length > 0; |
|
||||
|
|
||||
const hasMore = nextPageIndex !== null; |
|
||||
|
|
||||
const loadMore = useCallback(async () => { |
|
||||
if (loading || nextPageIndex === null) return; |
|
||||
setLoading(true); |
|
||||
try { |
|
||||
const { code, data, msg } = await post("/api/coupon/ApplyedList", { |
|
||||
paging: 1, |
|
||||
pageIndex: nextPageIndex, |
|
||||
pageSize: 10, |
|
||||
memberID, |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
setList([...list, ...data.list]); |
|
||||
setNextPageIndex( |
|
||||
nextPageIndex + 1 > data.allPage ? null : nextPageIndex + 1 |
|
||||
); |
|
||||
} else { |
|
||||
setNextPageIndex(null); |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
} |
|
||||
} catch (error) { |
|
||||
setNextPageIndex(null); |
|
||||
} finally { |
|
||||
setLoading(false); |
|
||||
} |
|
||||
}, [list, loading, nextPageIndex]); |
|
||||
return ( |
|
||||
<div className="ShopManager"> |
|
||||
<div className="btns"> |
|
||||
<div className="btn" onClick={() => setShowApplyModal(true)}> |
|
||||
申请 |
|
||||
</div> |
|
||||
<div className="btn" onClick={() => setShowWriteOffModal(true)}> |
|
||||
核销 |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div className="list-container" ref={listRef}> |
|
||||
<InfiniteScroll |
|
||||
loadMore={loadMore} |
|
||||
hasMore={hasMore} |
|
||||
useWindow={false} |
|
||||
getScrollParent={() => listRef && listRef.current} |
|
||||
> |
|
||||
{showNoData && ( |
|
||||
<> |
|
||||
<img className="noDataPic" src={noDataPic}></img> |
|
||||
<div className="noDataText"> |
|
||||
当前您还未发布礼券,请先申请,等待后台申请通过后,刷新页面显示 |
|
||||
</div> |
|
||||
</> |
|
||||
)} |
|
||||
{list !== null && |
|
||||
list.map((coupon) => ( |
|
||||
<div key={coupon.code} className={`coupon status${coupon.state}`}> |
|
||||
<div className="row"> |
|
||||
<div className="r1">礼券标题</div> |
|
||||
<div className="r2">{coupon.title}</div> |
|
||||
</div> |
|
||||
<div className="row"> |
|
||||
<div className="r1">发放数量</div> |
|
||||
<div className="r2">{coupon.totalCount}</div> |
|
||||
</div> |
|
||||
{coupon.state === 1 && ( |
|
||||
<div className="row"> |
|
||||
<div className="r1">已领取数</div> |
|
||||
<div className="r2">{coupon.received}</div> |
|
||||
</div> |
|
||||
)} |
|
||||
<div className="row"> |
|
||||
<div className="r1">使用期限</div> |
|
||||
<div className="r2"> |
|
||||
{coupon.beginTime}至{coupon.endTime} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className="status">{stateMap[coupon.state]}</div> |
|
||||
</div> |
|
||||
))} |
|
||||
{showListEnd && <ListEnd></ListEnd>} |
|
||||
</InfiniteScroll> |
|
||||
</div> |
|
||||
{showApplyModal && ( |
|
||||
<ApplyModal |
|
||||
onBack={() => { |
|
||||
setShowApplyModal(false); |
|
||||
setList([]); |
|
||||
setNextPageIndex(1); |
|
||||
}} |
|
||||
memberID={memberID} |
|
||||
></ApplyModal> |
|
||||
)} |
|
||||
{showWriteOffModal && ( |
|
||||
<WriteOffModal |
|
||||
onBack={() => setShowWriteOffModal(false)} |
|
||||
memberID={memberID} |
|
||||
></WriteOffModal> |
|
||||
)} |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
export default ShopManager; |
|
||||
@ -1,132 +0,0 @@ |
|||||
.ShopManager { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
background: linear-gradient( |
|
||||
180deg, |
|
||||
#f2f2f2 0%, |
|
||||
rgba(249, 249, 249, 0) 20.18% |
|
||||
); |
|
||||
border-radius: 18px 18px 0 0; |
|
||||
padding-top: 10px; |
|
||||
width: 100vw; |
|
||||
align-items: center; |
|
||||
overflow: hidden; |
|
||||
.btns { |
|
||||
display: flex; |
|
||||
margin-bottom: 10px; |
|
||||
width: calc(100vw - 20px); |
|
||||
.btn { |
|
||||
display: flex; |
|
||||
flex: 1; |
|
||||
font-weight: 400; |
|
||||
font-size: 17px; |
|
||||
color: #353230; |
|
||||
height: 48px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 10px; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
.btn + .btn { |
|
||||
margin-left: 9px; |
|
||||
} |
|
||||
} |
|
||||
.noDataPic { |
|
||||
margin-top: 64px; |
|
||||
width: 250px; |
|
||||
height: 250px; |
|
||||
} |
|
||||
.noDataText { |
|
||||
margin: 0 43px; |
|
||||
font-weight: 400; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
text-align: center; |
|
||||
color: #68655e; |
|
||||
} |
|
||||
.list-container { |
|
||||
flex: 1; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: scroll; |
|
||||
padding-top: 16px; |
|
||||
text-align: center; |
|
||||
scroll-behavior: smooth; |
|
||||
|
|
||||
&::-webkit-scrollbar { |
|
||||
display: none; |
|
||||
} |
|
||||
.coupon { |
|
||||
position: relative; |
|
||||
width: calc(100vw - 20px); |
|
||||
border-radius: 16px; |
|
||||
overflow: hidden; |
|
||||
padding: 24px; |
|
||||
.row { |
|
||||
height: 50px; |
|
||||
border-bottom: 1px solid rgba(240, 240, 240, 0.4); |
|
||||
|
|
||||
.r1 { |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #9d988f; |
|
||||
text-align: left; |
|
||||
} |
|
||||
.r2 { |
|
||||
font-weight: 600; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #353230; |
|
||||
margin-top: 6px; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
text-align: left; |
|
||||
} |
|
||||
} |
|
||||
.row + .row { |
|
||||
margin-top: 10px; |
|
||||
} |
|
||||
.status { |
|
||||
position: absolute; |
|
||||
width: 72px; |
|
||||
height: 32px; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
display: flex; |
|
||||
font-weight: 600; |
|
||||
font-size: 13px; |
|
||||
line-height: 18px; |
|
||||
color: #ffffff; |
|
||||
border-radius: 0px 0px 0px 14px; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
&.status0 { |
|
||||
background: linear-gradient(241.87deg, #ffffff 2.89%, #fffbf8 97.29%); |
|
||||
.status { |
|
||||
background: linear-gradient(90deg, #ecd3a6 5.56%, #dbb979 100%); |
|
||||
box-shadow: 4px 6px 18px rgba(214, 162, 101, 0.3); |
|
||||
} |
|
||||
} |
|
||||
&.status1 { |
|
||||
background: linear-gradient(241.87deg, #ffffff 2.89%, #fefff8 97.29%); |
|
||||
.status { |
|
||||
background: linear-gradient(270.4deg, #71c956 0.27%, #7add83 87.87%); |
|
||||
box-shadow: 4px 6px 18px rgba(151, 214, 101, 0.3); |
|
||||
} |
|
||||
} |
|
||||
&.status2 { |
|
||||
background: linear-gradient(241.87deg, #ffffff 2.89%, #fffafa 97.29%); |
|
||||
.status { |
|
||||
background: linear-gradient(270deg, #e76464 3.47%, #ffa0a0 90.28%); |
|
||||
box-shadow: 4px 6px 18px rgba(214, 101, 122, 0.3); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.coupon + .coupon { |
|
||||
margin-top: 8px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 42 KiB |
@ -1,26 +0,0 @@ |
|||||
import "./ShopTabs.scss"; |
|
||||
import card from "./card.svg"; |
|
||||
import cardActive from "./cardActive.svg"; |
|
||||
import ticket from "./ticket.svg"; |
|
||||
import ticketActive from "./ticketActive.svg"; |
|
||||
const ShopTabs = ({ showCoupons, setShowCoupons }) => { |
|
||||
return ( |
|
||||
<div className="ShopTabs"> |
|
||||
<div |
|
||||
className={`tab ${showCoupons ? "active" : ""}`} |
|
||||
onClick={() => setShowCoupons(true)} |
|
||||
> |
|
||||
<img src={showCoupons ? cardActive : card}></img> |
|
||||
我的礼包 |
|
||||
</div> |
|
||||
<div |
|
||||
className={`tab ${!showCoupons ? "active" : ""}`} |
|
||||
onClick={() => setShowCoupons(false)} |
|
||||
> |
|
||||
<img src={!showCoupons ? ticketActive : ticket}></img> |
|
||||
券管家 |
|
||||
</div> |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
export default ShopTabs; |
|
||||
@ -1,32 +0,0 @@ |
|||||
.ShopTabs { |
|
||||
display: flex; |
|
||||
width: calc(100vw - 20px); |
|
||||
height: 56px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
padding: 4px; |
|
||||
margin-bottom: 16px; |
|
||||
margin-top: 10px; |
|
||||
.tab { |
|
||||
display: flex; |
|
||||
flex: 1; |
|
||||
height: 48px; |
|
||||
font-weight: 500; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
color: #68655e; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
border-radius: 8px; |
|
||||
img { |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
&.active { |
|
||||
color: #ffffff; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 667 B |
|
Before Width: | Height: | Size: 665 B |
|
Before Width: | Height: | Size: 617 B |
|
Before Width: | Height: | Size: 615 B |
@ -1,148 +0,0 @@ |
|||||
import "./WriteOffModal.scss"; |
|
||||
import Modal from "react-modal"; |
|
||||
import { useState, useRef, useEffect, useCallback } from "react"; |
|
||||
import { post } from "../../../js/helpers/data-helper"; |
|
||||
import ScanModal from "../ScanModal/ScanModal"; |
|
||||
import InfiniteScroll from "react-infinite-scroller"; |
|
||||
import ListEnd from "../ListEnd/ListEnd"; |
|
||||
|
|
||||
const WriteOffModal = ({ onBack, memberID }) => { |
|
||||
const [orderNo, setOrderNo] = useState(""); |
|
||||
const [showScanModal, setShowScanModal] = useState(false); |
|
||||
const [list, setList] = useState([]); |
|
||||
const [nextPageIndex, setNextPageIndex] = useState(1); |
|
||||
const [loading, setLoading] = useState(false); |
|
||||
const hasMore = nextPageIndex !== null; |
|
||||
const [allCount, setAllCount] = useState(0); |
|
||||
const [month, setMonth] = useState(new Date().toJSON().slice(0, 7)); |
|
||||
const showListEnd = list !== null && list.length > 0; |
|
||||
const listRef = useRef(); |
|
||||
|
|
||||
const loadMore = useCallback(async () => { |
|
||||
if (loading || nextPageIndex === null) return; |
|
||||
setLoading(true); |
|
||||
try { |
|
||||
const { code, data, msg } = await post("/api/Coupon/WriteOffHis", { |
|
||||
paging: 1, |
|
||||
pageIndex: nextPageIndex, |
|
||||
pageSize: 10, |
|
||||
memberID, |
|
||||
month, |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
setList([...list, ...data.list]); |
|
||||
setNextPageIndex( |
|
||||
nextPageIndex + 1 > data.allPage ? null : nextPageIndex + 1 |
|
||||
); |
|
||||
setAllCount(data.allCount); |
|
||||
} else { |
|
||||
setNextPageIndex(null); |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
} |
|
||||
} catch (error) { |
|
||||
setNextPageIndex(null); |
|
||||
} finally { |
|
||||
setLoading(false); |
|
||||
} |
|
||||
}, [list, loading, nextPageIndex]); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (listRef.current) listRef.current.scrollTop = 0; |
|
||||
setNextPageIndex(1); |
|
||||
setAllCount(0); |
|
||||
setList([]); |
|
||||
}, [month]); |
|
||||
|
|
||||
const toast = (text) => |
|
||||
window.weui.toast(text, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
const writeOff = async (orderNo) => { |
|
||||
try { |
|
||||
const { code, msg } = await post("/api/coupon/writeoffcoupon", { |
|
||||
orderNo, |
|
||||
memberID, |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
toast("核销成功"); |
|
||||
return true; |
|
||||
} else { |
|
||||
toast(msg); |
|
||||
return false; |
|
||||
} |
|
||||
} catch (error) { |
|
||||
return false; |
|
||||
} |
|
||||
}; |
|
||||
const submitFromBtn = async (orderNo) => { |
|
||||
const result = await writeOff(orderNo); |
|
||||
if (result) { |
|
||||
setOrderNo(""); |
|
||||
} |
|
||||
}; |
|
||||
const handleCode = async (orderNo) => { |
|
||||
await writeOff(orderNo); |
|
||||
setShowScanModal(false); |
|
||||
}; |
|
||||
return ( |
|
||||
<Modal isOpen ariaHideApp={false} className="WriteOffModal"> |
|
||||
<div className="back" onClick={() => onBack && onBack()}></div> |
|
||||
<div className="title">核销</div> |
|
||||
<div className="search"> |
|
||||
<div className="icon"></div> |
|
||||
<input |
|
||||
type="number" |
|
||||
value={orderNo} |
|
||||
onChange={(e) => setOrderNo(e.target.value)} |
|
||||
></input> |
|
||||
</div> |
|
||||
<div className="scan" onClick={() => setShowScanModal(true)}></div> |
|
||||
{!!orderNo && ( |
|
||||
<div className="btn" onClick={() => submitFromBtn(orderNo)}> |
|
||||
确认核销 |
|
||||
</div> |
|
||||
)} |
|
||||
<div className="bar"> |
|
||||
<div>已核销({allCount}张)</div> |
|
||||
<input |
|
||||
type="month" |
|
||||
value={month} |
|
||||
onChange={(e) => setMonth(e.target.value)} |
|
||||
></input> |
|
||||
</div> |
|
||||
<div className="list-container" ref={listRef}> |
|
||||
<InfiniteScroll |
|
||||
pageStart={0} |
|
||||
loadMore={loadMore} |
|
||||
hasMore={hasMore} |
|
||||
useWindow={false} |
|
||||
getScrollParent={() => listRef && listRef.current} |
|
||||
> |
|
||||
{list !== null && |
|
||||
list.map((coupon) => ( |
|
||||
<div key={coupon.orderNo} className="coupon"> |
|
||||
<div className="block"> |
|
||||
<div className="r1">礼券标题</div> |
|
||||
<div className="r2">{coupon.title}</div> |
|
||||
</div> |
|
||||
<div className="block"> |
|
||||
<div className="r1">核销时间</div> |
|
||||
<div className="r2">{coupon.writeOffTime}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
))} |
|
||||
{showListEnd && <ListEnd></ListEnd>} |
|
||||
</InfiniteScroll> |
|
||||
</div> |
|
||||
{showScanModal && ( |
|
||||
<ScanModal |
|
||||
onBack={() => setShowScanModal(false)} |
|
||||
onCode={handleCode} |
|
||||
></ScanModal> |
|
||||
)} |
|
||||
</Modal> |
|
||||
); |
|
||||
}; |
|
||||
export default WriteOffModal; |
|
||||
@ -1,162 +0,0 @@ |
|||||
.WriteOffModal { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
background: #f6f6f6; |
|
||||
overflow: hidden; |
|
||||
.back { |
|
||||
position: absolute; |
|
||||
top: 10px; |
|
||||
left: 10px; |
|
||||
width: 60px; |
|
||||
height: 60px; |
|
||||
background: center / cover no-repeat url(./back.svg); |
|
||||
} |
|
||||
.title { |
|
||||
position: absolute; |
|
||||
top: 28px; |
|
||||
right: 16px; |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 20px; |
|
||||
line-height: 25px; |
|
||||
color: #000000; |
|
||||
} |
|
||||
.search { |
|
||||
position: absolute; |
|
||||
top: 94px; |
|
||||
left: 10px; |
|
||||
right: 108px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 10px; |
|
||||
height: 60px; |
|
||||
overflow: hidden; |
|
||||
.icon { |
|
||||
position: absolute; |
|
||||
top: 14px; |
|
||||
left: 14px; |
|
||||
width: 47px; |
|
||||
height: 32px; |
|
||||
background: center / cover no-repeat url(./search.svg); |
|
||||
} |
|
||||
input { |
|
||||
position: absolute; |
|
||||
left: 75px; |
|
||||
right: 0; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
margin: auto; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
border: none; |
|
||||
outline: none; |
|
||||
color: #353230; |
|
||||
&::placeholder { |
|
||||
color: #dad7d1; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.scan { |
|
||||
position: absolute; |
|
||||
top: 94px; |
|
||||
right: 16px; |
|
||||
width: 80px; |
|
||||
height: 60px; |
|
||||
background: center / cover no-repeat url(./scan.svg); |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
height: 56px; |
|
||||
left: 29px; |
|
||||
right: 28px; |
|
||||
bottom: 126px; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
line-height: 22px; |
|
||||
text-align: center; |
|
||||
color: #ffffff; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
border-radius: 10px; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
.bar { |
|
||||
position: absolute; |
|
||||
top: 178px; |
|
||||
left: 24px; |
|
||||
right: 24px; |
|
||||
height: 20px; |
|
||||
font-weight: 600; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #353230; |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
input { |
|
||||
outline: none; |
|
||||
border: none; |
|
||||
background: none; |
|
||||
} |
|
||||
&::after { |
|
||||
content: ""; |
|
||||
position: absolute; |
|
||||
left: -8px; |
|
||||
bottom: -8px; |
|
||||
right: -5px; |
|
||||
height: 1px; |
|
||||
background: #dad7d1; |
|
||||
opacity: 0.6; |
|
||||
} |
|
||||
} |
|
||||
.list-container { |
|
||||
position: absolute; |
|
||||
top: 206px; |
|
||||
bottom: 0px; |
|
||||
left: 10px; |
|
||||
right: 10px; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: scroll; |
|
||||
text-align: center; |
|
||||
&::-webkit-scrollbar { |
|
||||
display: none; |
|
||||
} |
|
||||
.coupon { |
|
||||
height: 170px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 16px; |
|
||||
padding: 24px; |
|
||||
margin-top: 10px; |
|
||||
.block { |
|
||||
height: 54px; |
|
||||
border-bottom: 1px solid rgba(240, 240, 240, 0.4); |
|
||||
text-align: left; |
|
||||
.r1 { |
|
||||
font-weight: 400; |
|
||||
font-size: 15px; |
|
||||
line-height: 20px; |
|
||||
color: #9d988f; |
|
||||
} |
|
||||
.r2 { |
|
||||
font-style: normal; |
|
||||
font-weight: 600; |
|
||||
font-size: 17px; |
|
||||
line-height: 22px; |
|
||||
color: #353230; |
|
||||
margin-top: 6px; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
} |
|
||||
.block + .block { |
|
||||
margin-top: 16px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 653 B |
|
Before Width: | Height: | Size: 62 KiB |
@ -1,121 +0,0 @@ |
|||||
import "./ShopCoupons.scss"; |
|
||||
import { useState, useEffect } from "react"; |
|
||||
import { post } from "../../js/helpers/data-helper"; |
|
||||
|
|
||||
const ShopCoupons = ({ onBack, shop, memberID }) => { |
|
||||
const [coupons, setCoupons] = useState([]); |
|
||||
const [receiving, setReceiving] = useState(false); |
|
||||
const getList = async () => { |
|
||||
try { |
|
||||
const { code, data, msg } = await post( |
|
||||
"/Api/Coupon/ShopDetailCouponList", |
|
||||
{ |
|
||||
paging: 0, |
|
||||
memberID, |
|
||||
shopCode: shop.code, |
|
||||
} |
|
||||
); |
|
||||
if (code !== "200") |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
else setCoupons(data); |
|
||||
} catch (error) { |
|
||||
console.warn(error); |
|
||||
} |
|
||||
}; |
|
||||
useEffect(() => { |
|
||||
getList(); |
|
||||
}, []); |
|
||||
const receive = async (coupon) => { |
|
||||
setReceiving(true); |
|
||||
try { |
|
||||
const { code, data, msg } = await post("/Api/Coupon/ShopCouponReceive", { |
|
||||
couponCode: coupon.code, |
|
||||
memberID, |
|
||||
}); |
|
||||
window.weui.toast(msg, { |
|
||||
className: "toast", |
|
||||
}); |
|
||||
if (code === "200") { |
|
||||
getList(); |
|
||||
} |
|
||||
} catch (error) { |
|
||||
console.warn(error); |
|
||||
} finally { |
|
||||
setReceiving(false); |
|
||||
} |
|
||||
}; |
|
||||
return ( |
|
||||
<div className="ShopCoupons"> |
|
||||
<div className="header"> |
|
||||
<div |
|
||||
className="back" |
|
||||
onClick={() => { |
|
||||
onBack && onBack(); |
|
||||
}} |
|
||||
></div> |
|
||||
{shop.name} |
|
||||
</div> |
|
||||
<div className="list"> |
|
||||
{coupons.map((coupon, i) => ( |
|
||||
<div className="item" key={coupon.code}> |
|
||||
<div className="left"> |
|
||||
<img className="avatar" src={shop.logoPath}></img> |
|
||||
</div> |
|
||||
<div className="right"> |
|
||||
<div className="r1"> |
|
||||
<div className="content">{coupon.title}</div> |
|
||||
<div |
|
||||
className={ |
|
||||
"btn " + |
|
||||
(coupon.detailReceived >= coupon.detailReceiveCount |
|
||||
? "disabled" |
|
||||
: "") |
|
||||
} |
|
||||
onClick={() => { |
|
||||
if ( |
|
||||
coupon.detailReceived >= coupon.detailReceiveCount || |
|
||||
receiving |
|
||||
) |
|
||||
return; |
|
||||
receive(coupon); |
|
||||
}} |
|
||||
> |
|
||||
{coupon.detailReceived >= coupon.detailReceiveCount |
|
||||
? "已领取" |
|
||||
: "领券"} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className="r2"> |
|
||||
<div>使用期限</div> |
|
||||
<div> |
|
||||
{coupon.beginTime}至{coupon.endTime} |
|
||||
</div> |
|
||||
<div |
|
||||
className="desc" |
|
||||
onClick={() => { |
|
||||
coupon.isOpen = !coupon.isOpen; |
|
||||
setCoupons([...coupons]); |
|
||||
}} |
|
||||
> |
|
||||
查看详情 |
|
||||
<div |
|
||||
className={"icon " + (coupon.isOpen ? "open" : "")} |
|
||||
></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
{!!coupon.isOpen && ( |
|
||||
<div className="r3"> |
|
||||
<div className="title">使用规则</div> |
|
||||
<div className="content">{coupon.couponRules}</div> |
|
||||
</div> |
|
||||
)} |
|
||||
</div> |
|
||||
</div> |
|
||||
))} |
|
||||
</div> |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
export default ShopCoupons; |
|
||||
@ -1,144 +0,0 @@ |
|||||
.ShopCoupons { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 100vw; |
|
||||
height: 100vh; |
|
||||
background: #f3f4f8; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
.header { |
|
||||
flex: 0 0 43px; |
|
||||
display: flex; |
|
||||
padding: 9px 16px 10px 18px; |
|
||||
justify-content: space-between; |
|
||||
font-weight: 600; |
|
||||
font-size: 20px; |
|
||||
line-height: 25px; |
|
||||
color: #323337; |
|
||||
white-space: nowrap; |
|
||||
align-items: center; |
|
||||
.back { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
background: center / cover no-repeat url(./back.svg); |
|
||||
} |
|
||||
} |
|
||||
.list { |
|
||||
flex: 1; |
|
||||
overflow-x: hidden; |
|
||||
overflow-y: auto; |
|
||||
padding: 0 10px; |
|
||||
* { |
|
||||
display: flex; |
|
||||
} |
|
||||
.item { |
|
||||
background: #ffffff; |
|
||||
border: 1px solid #edeff3; |
|
||||
box-shadow: 2px 6px 8px rgba(104, 110, 127, 0.08); |
|
||||
border-radius: 18px; |
|
||||
padding: 16px; |
|
||||
.left { |
|
||||
flex: 0 0 40px; |
|
||||
.avatar { |
|
||||
width: 40px; |
|
||||
height: 40px; |
|
||||
padding: 5px; |
|
||||
border: 1px solid #edeff3; |
|
||||
box-shadow: 2px 6px 8px rgba(104, 110, 127, 0.08); |
|
||||
border-radius: 38px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
.right { |
|
||||
flex: 1; |
|
||||
flex-direction: column; |
|
||||
.r1 { |
|
||||
padding-left: 10px; |
|
||||
height: 40px; |
|
||||
justify-content: space-between; |
|
||||
flex: 1; |
|
||||
align-items: center; |
|
||||
.content { |
|
||||
display: block; |
|
||||
width: calc(100vw - 192px); |
|
||||
font-size: 20px; |
|
||||
color: #323337; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
.btn { |
|
||||
flex: 0 0 90px; |
|
||||
width: 90px; |
|
||||
height: 38px; |
|
||||
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%); |
|
||||
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2); |
|
||||
border-radius: 10px; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
font-size: 14px; |
|
||||
color: #ffffff; |
|
||||
&.disabled { |
|
||||
background: #f3f4f8; |
|
||||
box-shadow: none; |
|
||||
color: #a1a5b3; |
|
||||
} |
|
||||
&:active { |
|
||||
opacity: 0.7; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.r2 { |
|
||||
margin-left: 10px; |
|
||||
margin-top: 18px; |
|
||||
border-top: 1px solid #edeff3; |
|
||||
padding-top: 6px; |
|
||||
font-size: 12px; |
|
||||
line-height: 18px; |
|
||||
color: #474a56; |
|
||||
flex-direction: column; |
|
||||
.desc { |
|
||||
margin-top: 10px; |
|
||||
font-size: 13px; |
|
||||
height: 18px; |
|
||||
color: #437af7; |
|
||||
align-items: center; |
|
||||
.icon { |
|
||||
margin-left: 2px; |
|
||||
width: 16px; |
|
||||
height: 16px; |
|
||||
background: center / cover no-repeat url(./arrow.svg); |
|
||||
transition: all 0.25s ease-in-out; |
|
||||
margin-left: 2px; |
|
||||
&.open { |
|
||||
transform: rotate(90deg); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.r3 { |
|
||||
flex-direction: column; |
|
||||
background: #f9f9fb; |
|
||||
border-radius: 8px; |
|
||||
padding: 10px; |
|
||||
.title { |
|
||||
font-size: 13px; |
|
||||
line-height: 18px; |
|
||||
color: #7a7e8d; |
|
||||
margin-bottom: 4px; |
|
||||
} |
|
||||
.content { |
|
||||
font-size: 12px; |
|
||||
line-height: 16px; |
|
||||
color: #a1a5b3; |
|
||||
opacity: 0.8; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.item + .item { |
|
||||
margin-top: 8px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 743 B |
|
Before Width: | Height: | Size: 481 B |