Browse Source

feat: 基础导航能力

pull/3/head
jiannibang 3 years ago
parent
commit
51023eeda8
  1. 211
      src/components/DefaultPopup/DefaultPopup.js
  2. BIN
      src/components/DefaultPopup/arrow.png
  3. BIN
      src/components/DefaultPopup/close.png
  4. BIN
      src/components/DefaultPopup/go.png
  5. BIN
      src/components/DefaultPopup/search.png
  6. 231
      src/components/DefaultPopup/style.scss
  7. 22
      src/components/Floors/Floors.js
  8. 76
      src/components/Floors/Floors.scss
  9. 184
      src/components/HeadBar/HeadBar.js
  10. 271
      src/components/HeadBar/HeadBar.scss
  11. BIN
      src/components/HeadBar/arrow.png
  12. BIN
      src/components/HeadBar/back.png
  13. BIN
      src/components/HeadBar/end.png
  14. BIN
      src/components/HeadBar/start.png
  15. BIN
      src/components/HeadBar/switch.png
  16. 260
      src/components/Malls/Malls.js
  17. 242
      src/components/Malls/Malls.scss
  18. BIN
      src/components/Malls/close_white.png
  19. BIN
      src/components/Malls/pos.png
  20. BIN
      src/components/Malls/search.png
  21. BIN
      src/components/Malls/up.png
  22. BIN
      src/components/More/2d.png
  23. BIN
      src/components/More/3d.png
  24. 53
      src/components/More/More.js
  25. 53
      src/components/More/More.scss
  26. 87
      src/components/NavBottom/NavBottom.js
  27. 210
      src/components/NavBottom/NavBottom.scss
  28. BIN
      src/components/NavBottom/close.png
  29. BIN
      src/components/Options/2d.png
  30. BIN
      src/components/Options/3d.png
  31. 137
      src/components/Options/Options.js
  32. 106
      src/components/Options/Options.scss
  33. BIN
      src/components/Options/ft.png
  34. BIN
      src/components/Options/ft1.png
  35. BIN
      src/components/Options/ftb.png
  36. BIN
      src/components/Options/ftb1.png
  37. BIN
      src/components/Options/mute.png
  38. BIN
      src/components/Options/on.png
  39. BIN
      src/components/Options/shortest.png
  40. BIN
      src/components/Options/shortest1.png
  41. BIN
      src/components/Options/shortestb.png
  42. BIN
      src/components/Options/shortestb1.png
  43. BIN
      src/components/Options/zt.png
  44. BIN
      src/components/Options/zt1.png
  45. BIN
      src/components/Options/ztb.png
  46. BIN
      src/components/Options/ztb1.png
  47. 150
      src/components/Popup/Popup.js
  48. 195
      src/components/Popup/Popup.scss
  49. BIN
      src/components/Popup/ar.png
  50. BIN
      src/components/Popup/close.png
  51. BIN
      src/components/Popup/couponTop.png
  52. BIN
      src/components/Popup/desc.png
  53. BIN
      src/components/Popup/nav.png
  54. 28
      src/components/Shop/Shop.js
  55. 117
      src/components/Shop/Shop.scss
  56. BIN
      src/components/Shop/active.png
  57. BIN
      src/components/Shop/rowRight.png
  58. 27
      src/components/ShopList/ShopList.js
  59. 36
      src/components/ShopList/ShopList.scss
  60. 24
      src/components/ShopTabs/ShopTabs.js
  61. 32
      src/components/ShopTabs/ShopTabs.scss
  62. BIN
      src/components/ShopTabs/floor.png
  63. BIN
      src/components/ShopTabs/floor_active.png
  64. BIN
      src/components/ShopTabs/format.png
  65. BIN
      src/components/ShopTabs/format_active.png
  66. 103
      src/components/ShopsWithFilter/ShopsWithFilter.js
  67. 22
      src/components/ShopsWithFilter/ShopsWithFilter.scss
  68. 15
      src/components/SideBar/SideBar.js
  69. 20
      src/components/SideBar/SideBar.scss
  70. 28
      src/js/helpers/data-helper.js
  71. 212
      src/pages/Car/Car.js
  72. 255
      src/pages/Car/Car.scss
  73. BIN
      src/pages/Car/back.png
  74. BIN
      src/pages/Car/car.png
  75. BIN
      src/pages/Car/lot.png
  76. BIN
      src/pages/Car/lot_active.png
  77. BIN
      src/pages/Car/plate.png
  78. BIN
      src/pages/Car/plate_active.png
  79. 4
      src/pages/Car/plus.svg
  80. 277
      src/pages/Index/Index.js
  81. 107
      src/pages/Index/Index.scss
  82. BIN
      src/pages/Index/ar.png
  83. BIN
      src/pages/Index/more.png
  84. 15
      src/pages/Index/tabs/Tabs.js
  85. 3
      src/pages/Index/tabs/act.svg
  86. 3
      src/pages/Index/tabs/actActive.svg
  87. 10
      src/pages/Index/tabs/car.svg
  88. 10
      src/pages/Index/tabs/carActive.svg
  89. 3
      src/pages/Index/tabs/map.svg
  90. 3
      src/pages/Index/tabs/mapActive.svg
  91. 3
      src/pages/Index/tabs/my.svg
  92. 3
      src/pages/Index/tabs/myActive.svg
  93. BIN
      src/pages/Index/topRight.png
  94. 104
      src/pages/Keyboard/Keyboard.js
  95. 128
      src/pages/Keyboard/Keyboard.scss
  96. BIN
      src/pages/Keyboard/backspace.png
  97. 19
      src/pages/Shops/Shops.js
  98. 62
      src/pages/Shops/Shops.scss
  99. BIN
      src/pages/Shops/back.png
  100. BIN
      src/pages/Shops/close.png

211
src/components/DefaultPopup/DefaultPopup.js

@ -1,211 +0,0 @@
import "./style.scss";
import React, { useState, useEffect } from "react";
import search from "./search.png";
import close from "./close.png";
import go from "./go.png";
import arrow from "./arrow.png";
import ShopsWithFilter from "../ShopsWithFilter/ShopsWithFilter";
const STATES = {
init: 0,
moreFac: 1,
facList: 2,
};
export const DefaultPopupStates = STATES;
const initMarginBottom = 47;
const DefaultPopup = ({
state,
setState,
onSearch,
facilities,
onClickFac,
mall,
onClick,
setEnd,
hasTab,
blurMap = () => {},
}) => {
const marginBottomStateMap = {
0: 47,
1: hasTab
? window.innerHeight - 52 - 179 - 98
: window.innerHeight - 52 - 179,
};
const baseMarginBottom = marginBottomStateMap[state];
const [facList, setFacList] = useState(null);
const [focused, setFocused] = useState(null);
const [start, setStart] = useState(null);
const [marginBottom, setMarginBottom] = useState(null);
const [doTransition, setdoTransition] = useState(false);
useEffect(() => {
setdoTransition(true);
setMarginBottom(baseMarginBottom);
setTimeout(() => {
setdoTransition(false);
}, 500);
}, [state]);
const handleTouchStart = (e) => {
if (start) return;
setStart({
identifier: e.changedTouches[0].identifier,
y: e.changedTouches[0].clientY,
});
};
const handleTouchMove = (e) => {
if (!start) return;
const touch = Array.from(e.changedTouches).find(
({ identifier }) => identifier === start.identifier
);
if (!touch) return;
const delta = touch.clientY - start.y;
setMarginBottom(baseMarginBottom - delta);
};
const handleTouchEnd = (e) => {
if (!start) return;
const touch = Array.from(e.changedTouches).find(
({ identifier }) => identifier === start.identifier
);
if (!touch) return;
setStart(null);
const delta = touch.clientY - start.y;
const newState =
state === STATES.init && delta < -100
? STATES.moreFac
: state === STATES.moreFac && delta > 100
? STATES.init
: state;
if (state === newState) {
setdoTransition(true);
setMarginBottom(baseMarginBottom);
setTimeout(() => {
setdoTransition(false);
}, 500);
} else setState(newState);
};
return (
<>
{state === STATES.init || state === STATES.moreFac ? (
<div
className={"dp" + (state === STATES.moreFac ? " more-fac" : "")}
style={{
marginBottom: marginBottom + "px",
transition: !doTransition ? "none" : "margin-bottom 0.5s ease",
}}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchCancel={handleTouchEnd}
onTouchEnd={handleTouchEnd}
>
<div
className="ts"
onClick={() =>
setState(state === STATES.moreFac ? STATES.init : STATES.moreFac)
}
>
<img className="t1" src={arrow} />
</div>
<div className="search" onClick={onSearch}>
<img className="icon" src={search}></img>
<div className="sep"></div>
搜索店铺
</div>
<div className="facs">
{Object.entries(facilities).map(([name, list]) => (
<div
className="fac"
key={name}
onClick={() => {
list.sort((a, b) => a.floorOrder - b.floorOrder);
setFacList(list);
setState(STATES.facList);
}}
>
<img src={list[0].url}></img>
{name}
</div>
))}
</div>
</div>
) : (
<>
<img
src={close}
className="close"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setState(STATES.init);
setFacList(null);
blurMap();
}}
></img>
<div className="dp1">
{facList &&
facList.map((fac, i) => {
const showRow1 =
i === 0 || fac.floorName !== facList[i - 1].floorName;
const isActive = focused === fac.id;
return (
<div key={fac.id}>
{showRow1 && (
<div className={"row1" + (i === 0 ? "" : " has-border")}>
{fac.floorName}
</div>
)}
<div
className={[
"row2",
isActive ? "active" : "",
!showRow1 ? "has-margin" : "",
].join(" ")}
onClick={() => {
setFocused(fac.id);
onClickFac(fac.id);
}}
>
{fac.name}
<span className="meta">{fac.floorName}</span>
{isActive && (
<div
className="go"
src={go}
onClick={(e) => {
e.stopPropagation();
setState(STATES.init);
onClickFac(fac.id);
}}
>
GO
</div>
)}
</div>
</div>
);
})}
</div>
</>
)}
{state !== STATES.facList && (
<div
className="sf"
onClick={() => {
setState(STATES.moreFac);
}}
>
<ShopsWithFilter
mall={mall}
onClick={(e) => {
setState(STATES.init);
onClick(e);
}}
wingHeight="calc(100vh - 310px)"
></ShopsWithFilter>
</div>
)}
</>
);
};
export default DefaultPopup;

BIN
src/components/DefaultPopup/arrow.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 B

BIN
src/components/DefaultPopup/close.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

BIN
src/components/DefaultPopup/go.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
src/components/DefaultPopup/search.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

231
src/components/DefaultPopup/style.scss

@ -1,231 +0,0 @@
.dp {
position: relative;
width: calc(100vw - 20px);
margin-left: 10px;
height: 179px;
border-top-left-radius: 24px;
border-top-right-radius: 24px;
text-align: center;
position: relative;
padding: 14px 0 0 0;
background: #ffffff;
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08);
border-radius: 18px;
&::before {
position: absolute;
content: "";
top: 0;
left: -10px;
right: -10px;
height: 236px;
background: linear-gradient(
180deg,
rgba(243, 244, 248, 0) 0%,
#f3f4f8 41.53%,
#f3f4f8 100%
);
z-index: -1;
}
&::after {
position: absolute;
content: "";
left: -10px;
right: -10px;
top: 236px;
height: calc(100vh - 52px - 236px);
background: #f3f4f8;
z-index: -1;
}
&.more-fac {
.t1,
.t2 {
transform: rotate(180deg);
}
.facs {
max-height: 333px;
overflow-y: scroll;
}
}
.ts {
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 0;
width: 24px;
height: 24px;
.t1 {
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 3px;
width: 33px;
height: 7px;
border-radius: 5px;
}
}
.search {
position: relative;
display: flex;
align-items: center;
margin: 0 14px;
height: 60px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 16px;
color: #323337;
text-align: left;
background: #f3f4f8;
border: 1px solid #edeff3;
box-sizing: border-box;
border-radius: 10px;
padding-left: 14px;
.icon {
width: 24px;
height: 24px;
}
.sep {
width: 1px;
height: 16px;
background: #c9cbd1;
margin: 0 14px;
}
}
.facs {
display: inline-flex;
align-items: flex-start;
overflow-x: auto;
overflow-y: hidden;
width: 100%;
white-space: nowrap;
margin-top: 20px;
padding-left: 20px;
height: 75px;
.fac {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 65px;
margin-right: 20px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 11px;
line-height: 15px;
text-align: center;
color: #474a56;
align-items: center;
img {
display: block;
width: 44px;
height: 44px;
}
}
}
}
.close {
position: absolute;
top: 16px;
right: 26px;
width: 24px;
height: 24px;
z-index: 10;
}
.dp1 {
position: relative;
margin: 0 10px 26px 10px;
height: 326px;
border-radius: 18px;
background: #ffffff;
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08);
text-align: center;
padding: 14px;
overflow-x: hidden;
overflow-y: auto;
.row1,
.row2 {
text-align: left;
line-height: 48px;
height: 48px;
}
.row1 {
font-family: DINPro;
font-style: normal;
font-weight: bold;
font-size: 24px;
line-height: 48px;
height: 48px;
color: #323337;
padding: 0 16px;
&.has-border {
position: relative;
padding-top: 24px;
height: 72px;
&::after {
position: absolute;
content: "";
top: 12px;
left: 0;
right: 0;
border-top: 1px dashed #edeff3;
}
}
}
.row2 {
display: flex;
position: relative;
padding-left: 16px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 16px;
color: #323337;
background: #f9f9fb;
border-radius: 12px;
&.has-margin {
margin-top: 4px;
}
&.active {
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
color: #ffffff;
border-radius: 12px;
.meta {
color: #ffffff;
}
}
.meta {
margin-left: 16px;
font-family: DINPro;
font-style: normal;
font-weight: normal;
font-size: 17px;
color: #a1a5b3;
}
.go {
position: absolute;
top: 8px;
right: 8px;
width: 96px;
height: 32px;
background: #ffffff;
box-shadow: 0px 2px 6px rgba(93, 172, 249, 0.2);
border-radius: 8px;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 32px;
text-align: center;
color: #437af7;
}
}
}
.sf {
position: absolute;
top: 177px;
left: 0;
}

22
src/components/Floors/Floors.js

@ -11,9 +11,7 @@ const Floors = ({
onClickFloor, onClickFloor,
popupHeight, popupHeight,
showNav, showNav,
isNavEnd,
end,
hasCoupon,
start,
}) => { }) => {
const [list, setList] = useState([]); const [list, setList] = useState([]);
useEffect(() => { useEffect(() => {
@ -37,23 +35,17 @@ const Floors = ({
block: "center", block: "center",
}); });
}); });
return !showNav ? ( return !showNav ? (
<div
className={[
"floor-list",
showNav ? " show-nav" : "",
isNavEnd ? " nav-end" : "",
hasCoupon ? "has-coupon" : "",
].join(" ")}
style={{ bottom: popupHeight + 66 + "px" }}
>
<div className="floor-list" style={{ bottom: popupHeight + 66 + "px" }}>
<ul> <ul>
{list.map(({ name, index, ref }) => ( {list.map(({ name, index, ref }) => (
<li <li
key={index} key={index}
ref={ref} ref={ref}
className={sceneIndex === index ? "active" : ""}
className={[
sceneIndex === index ? "active" : "",
start && start.floorOrder === index ? "current" : "",
].join(" ")}
onClick={() => { onClick={() => {
if (!clickable) return false; if (!clickable) return false;
setSceneIndex(index); setSceneIndex(index);
@ -64,8 +56,6 @@ const Floors = ({
</li> </li>
))} ))}
</ul> </ul>
<img alt="上箭头" className="top" src={up}></img>
<img alt="下箭头" className="bottom" src={up}></img>
</div> </div>
) : ( ) : (
<div className="floor-sub"> <div className="floor-sub">

76
src/components/Floors/Floors.scss

@ -1,65 +1,55 @@
.floor-list { .floor-list {
position: absolute;
top: -172px;
left: 10px;
height: 160px;
width: 40px;
padding: 10px 0;
height: 72px;
width: 100vw;
flex: 0 0 72px;
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
z-index: 1000; z-index: 1000;
background: #ffffff;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
border-radius: 12px;
&.has-coupon {
top: -211px;
}
.show-nav {
top: -442px;
}
&.nav-end {
top: -212px;
}
background: var(--guide-floorBg);
ul { ul {
overflow-x: hidden;
overflow-y: auto;
height: 140px;
overflow-x: auto;
overflow-y: hidden;
width: 100vw;
height: 72px;
white-space: nowrap;
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }
} }
li { li {
position: relative;
display: inline-block; display: inline-block;
line-height: 32px;
font-family: DINPro; font-family: DINPro;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 14px;
font-size: 16px;
text-align: center; text-align: center;
color: #323337;
width: 32px;
height: 32px;
margin: 4px;
&.active {
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
border-radius: 8px;
color: #fff;
}
}
img {
color: var(--guide-floorColor);
width: 58px;
line-height: 72px;
height: 72px;
&.current {
background: rgba(0, 0, 0, 0.1);
&::after {
position: absolute; position: absolute;
width: 8px;
height: 3px;
margin: auto;
left: 0; left: 0;
right: 0; right: 0;
&.top {
top: 7px;
bottom: 0;
height: 20px;
display: flex;
content: "您在本层";
background: var(--guide-currentBg);
font-weight: 700;
font-size: 8px;
color: var(--guide-currentColor);
align-items: center;
justify-content: center;
}
} }
&.bottom {
bottom: 7px;
transform-origin: center;
transform: rotate(180deg);
&.active {
background: var(--guide-floorActiveBg);
color: var(--guide-floorActiveColor);
} }
} }
} }

184
src/components/HeadBar/HeadBar.js

@ -1,184 +0,0 @@
import React, { useState, useEffect } from "react";
import ShopList from "../ShopList/ShopList.js";
import "./HeadBar.scss";
import { searchTypes } from "../Options/Options";
import backpng from './back.png'
const HeadBar = ({
mall,
exit,
start,
end,
floors,
onSwap,
shop,
onSetStart,
onSetEnd,
isPick,
setIsPick,
blurMap,
showSearchType,
onClickSearchType,
searchType,
onIsTypingChange
}) => {
const [isTypingStart, setIsTypingStart] = useState(false);
const [isTypingEnd, setIsTypingEnd] = useState(false);
const isTyping = isTypingStart || isTypingEnd;
const [q, setQ] = useState(null);
const onlyShowStart = isTypingStart || (!start && isPick);
const onlyShowEnd = isTypingEnd || (!end && isPick);
const showStart = !onlyShowEnd;
const showEnd = !onlyShowStart;
const showBoth = !(isPick || isTyping);
const hasBoth = start && end;
const startValue =
q !== null ? q : isPick ? (shop ? shop.name : "") : start ? start.name : "";
const endValue =
q !== null ? q : isPick ? (shop ? shop.name : "") : end ? end.name : "";
useEffect(() => { onIsTypingChange(isTyping) }, [isTyping])
return (
<div
className={"head-bar" + (showBoth ? " double" : "")}
onClick={() => blurMap()}
>
<div
className="back"
onClick={() => {
if (isPick) setIsPick(false);
else if (isTypingStart) {
setQ(null);
setIsTypingStart(false);
} else if (isTypingEnd) {
setQ(null);
setIsTypingEnd(false);
} else exit();
}}
>
<img src={backpng}></img>
</div>
<div className="content">
{showBoth && <div className="dots"></div>}
{showStart && (
<div className={"row start" + (onlyShowStart ? " single" : "")}>
<div className="text">
<input
value={startValue}
onFocus={() => setIsTypingStart(true)}
onChange={(e) => setQ(e.target.value)}
readOnly={isPick}
disabled={isPick}
placeholder={isPick ? "请点击地图选择起点" : "请输入起点"}
></input>
{(start || (isPick && shop)) && (
<span className="label">
{floors[(start ? start : shop).floorOrder][1]}
</span>
)}
<div style={{ flex: 1 }}></div>
{start === null && isPick && (
<div
className='right'
onClick={() => {
setIsPick(false);
onSetStart(shop);
}}
>
开始导航
</div>
)}
{start === null && !isPick && !isTypingStart && (
<div
className="right"
onClick={() => {
setQ(null);
setIsPick(true);
setIsTypingStart(false);
setIsTypingEnd(false);
}}
>
地图选点
</div>
)}
</div>
</div>
)}
{showEnd && (
<div className={"row end" + (isPick ? " single" : "")}>
<div className={"text " + (isTypingEnd ? '' : 'has-border')}>
<input
value={endValue}
onFocus={() => setIsTypingEnd(true)}
onChange={(e) => setQ(e.target.value)}
readOnly={isPick}
disabled={isPick}
placeholder={isPick ? "请点击地图选择终点" : "请输入终点"}
></input>
{((isPick && shop) || end) && (
<span className="label">
{floors[(end ? end : shop).floorOrder][1]}
</span>
)}
<div style={{ flex: 1 }}></div>
{end === null && isPick && (
<div
className={shop ? "right green" : "right grey"}
onClick={() => {
setIsPick(false);
onSetEnd(shop);
}}
>
开始导航
</div>
)}
{end === null && !isPick && !isTypingEnd && (
<div
className="right"
onClick={() => {
setQ(null);
setIsPick(true);
setIsTypingEnd(false);
}}
>
地图选点
</div>
)}
</div>
</div>
)}
{showBoth && <div className="switch" onClick={() => onSwap()}></div>}
</div>
{showBoth && !hasBoth && (
<div className={"banner " + (start === null ? "start" : "end")}>
请在顶部选择{!start ? "起" : "终"}
</div>
)}
{isTyping && q && (
<div className="shop-list-wrapper">
<ShopList
mall={mall}
q={q}
onClick={(shop) => {
if (isTypingStart) {
onSetStart(shop);
setQ(null);
setIsTypingStart(false);
}
if (isTypingEnd) {
onSetEnd(shop);
setQ(null);
setIsTypingEnd(false);
}
}}
top={"70px"}
isRow={true}
></ShopList>
</div>
)}
</div>
);
};
export default HeadBar;

271
src/components/HeadBar/HeadBar.scss

@ -1,271 +0,0 @@
.head-bar {
display: flex;
box-sizing: border-box;
width: calc(100vw - 20px);
margin-left: 10px;
margin-top: 10px;
font-size: 16px;
line-height: 44px;
position: relative;
z-index: 1;
height: 64px;
position: relative;
border-radius: 12px;
align-items: center;
pointer-events: auto;
&.double {
height: 114px;
.back {
height: 114px;
}
.content {
height: 114px;
}
}
.back {
display: flex;
justify-content: center;
align-items: center;
position: relative;
background: #ffffff;
flex: 0 0 50px;
margin-right: 8px;
height: 64px;
border-radius: 12px;
img {
width: 32px;
height: 32px;
}
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
background: #ffffff;
height: 64px;
z-index: 2;
flex: 1;
position: relative;
border-radius: 12px;
.dots {
position: absolute;
top: 0;
bottom: 0;
left: 23px;
width: 2px;
height: 2px;
border-radius: 50%;
background: #c9cbd1;
margin: auto 0;
&::before {
content: "";
display: block;
position: absolute;
top: -6px;
width: 2px;
height: 2px;
border-radius: 50%;
background: #c9cbd1;
left: 0;
right: 0;
margin: 0 auto;
}
&::after {
content: "";
display: block;
position: absolute;
bottom: -6px;
width: 2px;
height: 2px;
border-radius: 50%;
background: #c9cbd1;
left: 0;
right: 0;
margin: 0 auto;
}
}
.row {
position: relative;
line-height: 57px;
height: 57px;
padding-left: 48px;
padding-right: 49px;
&.start {
background: 16px center/16px 16px no-repeat url("./start.png");
}
&.end {
background: 16px center/16px 16px no-repeat url("./end.png");
}
&.single {
padding-right: 10px;
}
.text {
display: flex;
align-items: center;
input {
border: none;
background: transparent;
display: inline-block;
line-height: 57px;
outline: none;
width: 100%;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 18px;
color: #323337;
}
::placeholder {
font-size: 16px;
font-weight: 400;
color: #c9cbd1;
}
&.has-border {
border-top: 1px solid rgba(238, 238, 238, 0.7);
}
.label {
display: inline-block;
flex: 0 0 30px;
text-align: right;
margin-left: 8px;
font-style: normal;
font-weight: bold;
font-size: 12px;
color: #b3aea7;
}
.right {
background: #f3f4f8;
border: 1px solid #edeff3;
box-sizing: border-box;
border-radius: 8px;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 12px;
line-height: 33px;
color: #437af7;
flex: 0 0 80px;
text-align: center;
display: inline-block;
white-space: nowrap;
margin-left: 8px;
}
}
}
.switch {
position: absolute;
width: 49px;
height: 32px;
background-image: url("./switch.png");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
top: 0;
bottom: 0;
right: 0;
margin: auto 0;
}
}
.banner {
position: absolute;
display: flex;
background: rgba(0, 0, 0, 0.6);
width: 237px;
line-height: 40px;
height: 40px;
text-align: center;
bottom: -48px;
left: 0;
right: 0;
margin: auto;
font-family: PingFang SC;
font-style: normal;
font-weight: normal;
font-size: 14px;
color: #ffffff;
border-radius: 20px;
justify-content: center;
align-items: center;
&.start::before {
content: "";
display: inline-block;
width: 16px;
height: 16px;
margin-right: 8px;
vertical-align: middle;
background-image: url("./start.png");
background-size: contain;
}
&.end::before {
content: "";
display: inline-block;
width: 16px;
height: 16px;
margin-right: 8px;
vertical-align: middle;
background-image: url("./end.png");
background-size: contain;
}
&::after {
content: "";
display: inline-block;
margin-left: 8px;
width: 16px;
height: 16px;
vertical-align: middle;
background-image: url("./arrow.png");
background-size: contain;
}
}
.shop-list-wrapper {
position: absolute;
top: 64px;
left: -10px;
width: 100vw;
height: calc(100vh - 74px);
overflow-x: hidden;
overflow-y: auto;
}
.search-type {
position: absolute;
top: 100px;
width: 100vw;
height: 40px;
line-height: 40px;
background: #fff;
display: flex;
color: #404040;
left: 0;
font-size: 12px;
.el {
flex: 1 1 33%;
text-align: center;
span {
position: relative;
display: inline-block;
img {
width: 18px;
height: 18px;
vertical-align: middle;
margin-right: 8px;
}
&.active {
color: #0074ed;
}
&.active {
&::after {
content: "";
position: absolute;
width: 100%;
height: 4px;
background: #0074ed;
bottom: 0;
left: 0;
}
}
}
}
}
}

BIN
src/components/HeadBar/arrow.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

BIN
src/components/HeadBar/back.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 841 B

BIN
src/components/HeadBar/end.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/components/HeadBar/start.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/components/HeadBar/switch.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

260
src/components/Malls/Malls.js

@ -1,260 +0,0 @@
import React, { useState, useEffect, useContext } from "react";
import { ListView } from "antd-mobile";
import Modal from "react-modal";
import "./Malls.scss";
import search from "./search.png";
import pos from "./pos.png";
import close_white from "./close_white.png";
import up from "./up.png";
import {
Mall,
cityMallsGetter,
CityMall,
} from "../../js/helpers/data-helper.js";
import { MallCode } from "../../pages/Index/Index";
const getSectionData = (dataBlob, sectionID) => dataBlob[sectionID];
const getRowData = (dataBlob, sectionID, rowID) => dataBlob[rowID];
function genData(ds, cityMalls) {
const dataBlob = {};
const sectionIDs = [];
const rowIDs = [];
const groupByIndex = (list) =>
list.reduce((acc, nxt) => {
acc[nxt.index] = acc[nxt.index] ? [...acc[nxt.index], nxt] : [nxt];
return acc;
}, {});
const data = groupByIndex(cityMalls);
Object.keys(data).forEach((item, index) => {
sectionIDs.push(item);
dataBlob[item] = item;
rowIDs[index] = [];
data[item].forEach((city) => {
rowIDs[index].push(city.name);
dataBlob[city.name] = city;
});
});
return ds.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs);
}
const Malls = ({ isOpen, onRequestClose, setMallCode }) => {
const [q, setQ] = useState("");
const [showList, setShowList] = useState(false);
const [cities, setCities] = useState([]);
const [currentMall, setCurrentMall] = useState(null);
const [currentCity, setCurrentCity] = useState(null);
const [currentMalls, setCurrentMalls] = useState([]);
const [isMallExpand, setIsMallExpand] = useState(false);
const [dataSource, setDataSource] = useState(
new ListView.DataSource({
getRowData,
getSectionHeaderData: getSectionData,
rowHasChanged: (row1, row2) => row1 !== row2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
})
);
const mallCode = useContext(MallCode);
const setDefaultCityMall = (list) => {
setCurrentCity(list[0]);
setCurrentMall(list[0].malls[0]);
setCurrentMalls(list[0].malls);
};
useEffect(() => {
document.title = "城市商场选择";
cityMallsGetter().then((cityMalls) => {
setCities(cityMalls);
setDataSource(genData(dataSource, cityMalls));
if (cityMalls.length) {
const city = cityMalls.find(({ malls }) =>
malls.find(({ code }) => mallCode === code)
);
if (city) {
setCurrentCity(city);
const mall = city.malls.find(({ code }) => mallCode === code);
if (mall) setCurrentMall(mall);
setCurrentMalls(city.malls);
} else setDefaultCityMall(cityMalls);
}
});
}, [mallCode]);
return (
<Modal
isOpen={isOpen}
style={{ overlay: { zIndex: 10000, background: "#fff" } }}
ariaHideApp={false}
className="malls"
onRequestClose={() => onRequestClose()}
>
<div className="malls" onClick={() => setIsMallExpand(false)}>
<div className="input-wrapper">
<input
value={q}
className="input"
placeholder="输入城市进行搜索"
onChange={(e) => setQ(e.target.value)}
onFocus={() => setShowList(true)}
onBlur={() => !q && setShowList(false)}
></input>
</div>
<img className="search-icon" src={search}></img>
{q && (
<img className="close" src={close_white} onClick={() => setQ("")} />
)}
{showList && (
<div className="list">
{cities
.filter(({ name }) => name.includes(q))
.map((city) => (
<div
className="item"
key={city.name}
onClick={() => {
setCurrentCity(city);
setCurrentMall(city.malls[0]);
setCurrentMalls(city.malls);
setShowList(false);
}}
>
{city.name}
</div>
))}
</div>
)}
{!showList && (
<div className="main">
<div className="r1">
<div className="left">
<img className="pos" src={pos}></img>
{currentCity && <span>{currentCity.name}</span>}
&nbsp;&nbsp;
{currentMall && <span>{currentMall.name}</span>}
<img className="up" src={up}></img>
</div>
<span className="right">当前定位城市</span>
</div>
<div className="r2">切换商场</div>
<div
className="malls-wrapper"
onClick={() => {
setIsMallExpand(false);
}}
>
<div
className={"malls1" + (isMallExpand ? " expand" : "")}
onClick={(e) => {
e.stopPropagation();
}}
>
{currentMalls.map((mall) => (
<span
key={mall.code}
className="tag"
onClick={() => {
console.log("setMallCode", mall.code);
setCurrentMall(mall);
setIsMallExpand(false);
setMallCode(mall.code);
onRequestClose();
// Taro.reLaunch({
// url: `/pages/index/index?mallId=${mall.id}`
// });
}}
>
{mall.name}
</span>
))}
{!isMallExpand && (
<div
className="more"
onClick={(e) => {
e.stopPropagation();
setIsMallExpand(true);
}}
>
更多
</div>
)}
{isMallExpand && (
<img
className="fold"
src={up}
onClick={(e) => {
e.stopPropagation();
setIsMallExpand(false);
}}
></img>
)}
</div>
<ListView.IndexedList
dataSource={dataSource}
className="am-list sticky-list"
useBodyScroll
renderSectionHeader={(sectionData) => (
<div>
<div
className="sticky"
style={{
zIndex: 3,
}}
>
{sectionData}
</div>
</div>
)}
renderHeader={() => (
<div>
<div className="meta">切换城市</div>
<div className="city-buttons">
{cities.map((city) => (
<div
key={city.name}
className="city-button"
onClick={() => {
setCurrentCity(city);
setCurrentMall(city.malls[0]);
setCurrentMalls(city.malls);
}}
>
{city.name}
</div>
))}
</div>
</div>
)}
renderRow={(rowData) => (
<div
key={rowData.name}
className="city-button"
onClick={() => {
setCurrentCity(rowData);
setCurrentMalls(rowData.malls);
setCurrentMall(rowData.malls[0]);
}}
>
{rowData.name}
</div>
)}
quickSearchBarStyle={{
position: "absolute",
top: 25,
}}
delayTime={10}
delayActivityIndicator={
<div style={{ padding: 25, textAlign: "center" }}>
rendering...
</div>
}
/>
</div>
</div>
)}
</div>
</Modal>
);
};
export default Malls;

242
src/components/Malls/Malls.scss

@ -1,242 +0,0 @@
/*postcss-pxtransform disable*/
.malls {
position: relative;
width: 100vw;
height: 100vh;
box-sizing: border-box;
color: #5a5a5a;
font-family: SourceHanSansCN-Medium, SourceHanSansCN;
background: #fff;
box-sizing: border-box;
.search-icon {
position: absolute;
width: 13px;
height: 13px;
top: 21px;
left: 26px;
z-index: 1;
}
.close {
position: absolute;
border-radius: 50%;
background: #8d8d8d;
width: 20px;
height: 20px;
top: 17px;
right: 19px;
}
.input-wrapper {
padding: 12px 14px 0 14px;
.input {
padding: 5px 30px;
background: #ececec;
border-radius: 100px;
height: 30px;
line-height: 20px;
font-size: 11px;
box-sizing: border-box;
border: none;
width: 100%;
outline: none;
}
::placeholder {
color: #a9a9a9;
}
}
.list {
padding: 0 50px 0 15px;
line-height: 36px;
height: calc(100vh - 42px);
font-size: 12px;
overflow: scroll;
.item {
border-bottom: 1px solid #f4f4f4;
}
}
.main {
.r1 {
padding: 18px 15px;
line-height: 30px;
.left {
position: relative;
display: inline-block;
font-size: 14px;
background: rgba(244, 244, 244, 1);
border-radius: 8px;
border: 1px solid rgba(236, 236, 236, 1);
padding: 0 30px;
.pos {
position: absolute;
width: 14px;
height: 16px;
top: 7px;
left: 9px;
}
.up {
position: absolute;
right: 7.5px;
top: 12.5px;
width: 8px;
height: 5px;
transform-origin: center;
transform: rotate(90deg);
}
Text + Text {
margin-left: 22px;
}
}
.right {
margin-left: 15px;
font-size: 11px;
font-weight: 400;
color: rgba(169, 169, 169, 1);
}
}
.r2 {
padding-left: 15px;
color: #a9a9a9;
font-size: 11px;
line-height: 11px;
font-weight: 400;
}
.malls-wrapper {
height: calc(100vh - 119px);
.malls1 {
position: relative;
margin-top: 11px;
padding-left: 15px;
padding-right: 60px;
height: 32px;
overflow: hidden;
background: #fff;
z-index: 10;
.more {
position: absolute;
line-height: 30px;
color: #a9a9a9;
right: 14px;
font-size: 11px;
top: 0;
}
&.expand {
box-shadow: 0px 15px 12px 0px rgba(0, 0, 0, 0.22);
padding-right: 15px;
padding-bottom: 17px;
overflow: auto;
height: auto;
}
.tag {
color: #878787;
font-size: 12px;
padding: 0 11px;
border-radius: 15px;
border: 1px solid rgba(236, 236, 236, 1);
line-height: 30px;
display: inline-block;
margin-bottom: 12px;
margin-right: 10px;
}
.fold {
position: absolute;
bottom: 0;
width: 8px;
height: 5px;
padding: 8px 6.5px;
left: 0;
right: 0;
margin: auto;
}
.fold::after {
content: "";
position: absolute;
left: -5px;
right: -5px;
top: -5px;
bottom: -5px;
}
}
}
.am-indexed-list-container {
position: absolute;
top: 178px;
border-top: 1px solid #f4f4f4;
padding: 0 50px 0 15px;
height: calc(100vh - 178px);
width: 100vw;
box-sizing: border-box;
.am-indexed-list-quick-search-bar :first-child {
display: none !important;
}
.am-indexed-list-quick-search-bar {
top: 204px;
font-size: 11px;
transform: none;
right: 15px;
z-index: 1;
text-align: center;
li {
display: block;
padding: 0;
font-size: 11px;
color: #a9a9a9;
line-height: 15px;
height: 15px;
width: 15px;
}
li:active {
background: #0091ff;
color: white;
border-radius: 50%;
}
}
.at-list::after {
content: none;
}
.am-indexed-list-section-body {
line-height: 36px;
color: #878787;
font-size: 12px;
font-weight: 400;
border-bottom: 1px solid #f4f4f4;
background: none;
padding: 0;
}
.am-indexed-list-section-header {
font-size: 12px;
font-weight: 400;
border-bottom: 1px solid #f4f4f4;
padding: 0;
}
.am-list-body {
color: #5a5a5a;
line-height: 36px;
}
}
.meta {
font-size: 11px;
font-weight: 400;
margin-top: 7px;
padding: 11px 0;
color: #a9a9a9;
}
.city-buttons {
display: grid;
grid-column-gap: 10px;
grid-row-gap: 11px;
grid-auto-rows: 30px;
grid-auto-columns: 70px;
grid-template-columns: 1fr 1fr 1fr 1fr;
.city-button {
display: inline-block;
color: #878787;
font-size: 12px;
line-height: 30px;
background: rgba(244, 244, 244, 1);
border-radius: 4px;
text-align: center;
}
}
}
}

BIN
src/components/Malls/close_white.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

BIN
src/components/Malls/pos.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 998 B

BIN
src/components/Malls/search.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 936 B

BIN
src/components/Malls/up.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

BIN
src/components/More/2d.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 870 B

BIN
src/components/More/3d.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

53
src/components/More/More.js

@ -1,53 +0,0 @@
import React from "react";
import { searchTypes, audioOptions } from "../Options/Options";
import "./More.scss";
import flat from "./2d.png";
import thrD from "./3d.png";
const displayModes = [
{
id: 0,
name: "2D",
bg: flat,
},
{
id: 1,
name: "3D",
bg: thrD,
},
];
const More = ({
showHeadBar,
displayMode,
searchType,
onClickDisplayMode,
onClickSearchType,
}) => {
return (
<div className={"more " + (showHeadBar ? "has-header-top" : "")}>
<div className="types">
{searchTypes.map(({ id, name, bg, bgb }) => (
<div
key={id}
className={"btn " + (searchType === id ? "active" : "")}
onClick={() => {
onClickSearchType(id);
}}
>
<img src={searchType === id ? bgb : bg} />
<div>{name}</div>
</div>
))}
</div>
<div
className="btn big"
onClick={() => onClickDisplayMode(displayMode == 0 ? 1 : 0)}
>
<img src={displayMode == 0 ? flat : thrD}></img>
{displayMode == 0 ? "2D" : "3D"}
</div>
</div>
);
};
export default More;

53
src/components/More/More.scss

@ -1,53 +0,0 @@
.more {
position: absolute;
top: 10px;
right: 10px;
display: inline-flex;
flex-direction: column;
pointer-events: auto;
&.has-header-top {
top: 138px;
}
.types {
display: flex;
flex-direction: column;
width: 40px;
height: 160px;
background: #ffffff;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
border-radius: 12px;
justify-content: space-evenly;
align-items: center;
}
.btn {
display: inline-flex;
flex-direction: column;
width: 32px;
height: 48px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 10px;
line-height: 14px;
text-align: center;
color: #474a56;
background: #ffffff;
border-radius: 12px;
justify-content: center;
align-items: center;
img {
width: 24px;
height: 24px;
}
&.active {
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
color: #fff;
}
&.big {
width: 40px;
height: 56px;
margin-top: 8px;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
}
}
}

87
src/components/NavBottom/NavBottom.js

@ -36,33 +36,13 @@ const getImgByRouteSearchText = (txt) =>
: straight; : straight;
const NavBottom = ({ const NavBottom = ({
routeSearchAnimationType,
switchType,
onExit, onExit,
end, end,
meters, meters,
minutes, minutes,
paused,
puaseOrResume,
hidePause,
hideSwitch,
routeSearchText, routeSearchText,
percent, percent,
handleAR,
}) => { }) => {
const [showText, setShowText] = useState(false);
const [showNav, setShowNav] = useState(true);
useEffect(() => {
setShowText(true);
let timeout = setTimeout(() => {
clearTimeout(timeout);
setShowText(false);
}, 3000);
return () => {
clearTimeout(timeout);
setShowText(false);
};
}, [routeSearchAnimationType]);
let progressNum = parseInt(percent * 100); let progressNum = parseInt(percent * 100);
if (isNaN(progressNum)) return; if (isNaN(progressNum)) return;
if (progressNum < 0) progressNum = 0; if (progressNum < 0) progressNum = 0;
@ -70,44 +50,7 @@ const NavBottom = ({
const progressText = progressNum + "%"; const progressText = progressNum + "%";
return ( return (
<div className={"nav-bottom" + (hidePause ? " hide-pause" : "")}>
<div className="tabs">
<div
className={["tab", showNav ? "active" : ""].join(" ")}
onClick={() => setShowNav(true)}
>
<img src={showNav ? navActive : nav}></img>
导航
</div>
<div
className={["tab", !showNav ? "active" : ""].join(" ")}
onClick={() => setShowNav(false)}
>
<img src={showNav ? des : desActive}></img>
目的地
</div>
</div>
{showText && !hideSwitch && (
<div className="switch">
{routeSearchAnimationType === 1
? "已切转地图视角"
: "已切转方向标视角"}
</div>
)}
{!hideSwitch && (
<img
className="switch-pic"
src={
routeSearchAnimationType === 1
? notFollowDirection
: followDirection
}
onClick={() => {
switchType();
}}
/>
)}
{showNav ? (
<div className="nav-bottom">
<div className="nav"> <div className="nav">
<img <img
className="dir" className="dir"
@ -119,37 +62,24 @@ const NavBottom = ({
剩余<span className="val">{meters}</span> &nbsp;{" "} 剩余<span className="val">{meters}</span> &nbsp;{" "}
<span className="val">{minutes}</span> <span className="val">{minutes}</span>
</div> </div>
<img
alt="关闭"
className="close-icon"
src={closeButton}
onClick={() => onExit()}
></img>
<div className="progress"></div> <div className="progress"></div>
<div <div
className="bar" className="bar"
style={{ width: `calc((100vw - 56px) * ${progressNum / 100})` }}
style={{
width: `calc((100vw - 52px) * ${progressNum / 100} + 16px)`,
}}
></div> ></div>
<div <div
className="bubble" className="bubble"
style={{ style={{
left: `calc(((100vw - 56px) * ${progressNum / 100}) + 20px)`,
left: `calc((100vw - 52px) * ${progressNum / 100})`,
}} }}
> >
{progressText} {progressText}
</div> </div>
{!hidePause && (
<img
src={paused ? play : pause}
className="pause"
onClick={() => {
puaseOrResume();
}}
/>
)}
</div> </div>
) : (
<div className="destination"> <div className="destination">
{end.logoPath && <img className="avatar" src={end.logoPath} />} {end.logoPath && <img className="avatar" src={end.logoPath} />}
<img <img
@ -158,12 +88,9 @@ const NavBottom = ({
src={closeButton} src={closeButton}
onClick={() => onExit()} onClick={() => onExit()}
></img> ></img>
<div className="meta">正在导航到...</div>
<div className="name">{end.name}</div> <div className="name">{end.name}</div>
<div className="meta">
<div> {end.floorName}</div> <div>{end.shopFormat}</div>
</div>
</div> </div>
)}
</div> </div>
); );
}; };

210
src/components/NavBottom/NavBottom.scss

@ -1,55 +1,16 @@
.nav-bottom { .nav-bottom {
position: absolute; position: absolute;
width: calc(100vw - 20px); width: calc(100vw - 20px);
left: 8px;
bottom: 26px;
left: 10px;
bottom: 22px;
height: 220px;
background: #ffffff;
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05);
border-radius: 18px; border-radius: 18px;
height: 200px;
padding: 14px 0 0 14px;
background: #fff;
z-index: 30; z-index: 30;
.tabs {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
bottom: 14px;
left: 14px;
right: 14px;
height: 56px;
background: #f3f4f8;
border-radius: 10px;
.tab {
display: flex;
width: calc((100vw - 20px - 28px - 12px) / 2);
height: 48px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 22px;
color: #323337;
justify-content: center;
align-items: center;
img {
width: 20px;
height: 20px;
margin-right: 8px;
}
&.active {
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2);
border-radius: 10px;
color: #fff;
}
}
}
.nav { .nav {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 82px;
position: relative;
height: 110px;
.dir { .dir {
position: absolute; position: absolute;
top: 14px; top: 14px;
@ -91,40 +52,23 @@
margin: 0 4px; margin: 0 4px;
} }
} }
.exit {
position: absolute;
top: 20px;
right: 12px;
width: 48px;
height: 48px;
text-align: center;
border: 1px solid #e2e1df;
box-sizing: border-box;
border-radius: 12px;
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 48px;
color: #6a6665;
}
.progress { .progress {
position: absolute; position: absolute;
left: 20px;
right: 20px;
top: 108px;
height: 4px;
background: #edeff3;
border-radius: 5px;
left: 0;
right: 0;
bottom: -1px;
height: 2px;
background: rgba(0, 0, 0, 0.05);
z-index: 1; z-index: 1;
} }
.bar { .bar {
position: absolute; position: absolute;
left: 20px;
right: 20px;
top: 108px;
left: 0;
right: 0;
bottom: -2px;
height: 4px; height: 4px;
background: #437af7;
border-radius: 5px;
background: #516dd8;
z-index: 2; z-index: 2;
} }
@ -132,21 +76,19 @@
display: flex; display: flex;
position: absolute; position: absolute;
z-index: 3; z-index: 3;
width: 33px;
height: 14px;
top: 103.5px;
background: #ffffff;
width: 32px;
height: 15px;
bottom: -7.5px;
background: linear-gradient(113.71deg, #435acd 0%, #749cf3 100%);
text-align: center; text-align: center;
border: 2px solid #437af7;
border-radius: 12px; border-radius: 12px;
font-family: DINPro; font-family: DINPro;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
font-size: 10px; font-size: 10px;
color: #437af7;
color: #fff;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
transform: translate(-50%, 0);
} }
.close-icon { .close-icon {
@ -199,11 +141,8 @@
} }
} }
.destination { .destination {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 82px;
position: relative;
height: 110px;
.avatar { .avatar {
position: absolute; position: absolute;
width: 80px; width: 80px;
@ -217,15 +156,15 @@
.close-icon { .close-icon {
position: absolute; position: absolute;
top: 16px;
right: 16px;
width: 24px;
height: 24px;
top: 14px;
right: 14px;
width: 52px;
height: 82px;
z-index: 10; z-index: 10;
} }
.name { .name {
position: absolute; position: absolute;
top: 24px;
top: 57px;
left: 108px; left: 108px;
font-family: PingFang SC; font-family: PingFang SC;
font-style: normal; font-style: normal;
@ -233,7 +172,7 @@
font-size: 24px; font-size: 24px;
line-height: 34px; line-height: 34px;
color: #323337; color: #323337;
right: 20px;
right: 80px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@ -241,95 +180,12 @@
.meta { .meta {
display: flex; display: flex;
position: absolute; position: absolute;
top: 68px;
top: 29px;
left: 108px; left: 108px;
right: 20px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-weight: 600;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
color: #a1a5b3;
align-items: center;
justify-content: space-between;
}
color: rgba(0, 0, 0, 0.4);
} }
.switch {
position: absolute;
top: -52px;
right: 0;
height: 40px;
line-height: 40px;
color: #fff;
border-radius: 85px;
font-size: 12px;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
background: rgba(0, 0, 0, 0.2);
padding-left: 12px;
padding-right: 42px;
animation: 3s ease-out fadeout;
@keyframes fadeout {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
}
.switch-pic {
position: absolute;
top: -52px;
right: 0;
width: 40px;
height: 40px;
vertical-align: middle;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
}
.ar-btn {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
position: absolute;
width: 111px;
height: 40px;
left: 0;
top: -52px;
background: #ffffff;
border-radius: 20px;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 40px;
color: #474a56;
img {
width: 24px;
height: 24px;
margin-right: 8px;
}
}
.br {
margin-bottom: 8px;
}
.gold {
font-weight: 400;
color: #b48764;
}
.big {
font-size: 20px;
font-family: DINPro-Bold, DINPro;
font-weight: bold;
margin: 0 5px;
}
.pause {
position: absolute;
width: 40px;
height: 40px;
top: -100px;
right: 0;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
} }
} }

BIN
src/components/NavBottom/close.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/components/Options/2d.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/components/Options/3d.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

137
src/components/Options/Options.js

@ -1,137 +0,0 @@
import React from "react";
import Modal from "react-modal";
import flat from "./2d.png";
import thrD from "./3d.png";
import on from "./on.png";
import mute from "./mute.png";
import ft from "./ft.png";
import ftb from "./ftb.png";
import ztb from "./ztb.png";
import zt from "./zt.png";
import shortest from "./shortest.png";
import shortestb from "./shortestb.png";
import ft1 from "./ft1.png";
import ftb1 from "./ftb1.png";
import ztb1 from "./ztb1.png";
import zt1 from "./zt1.png";
import shortest1 from "./shortest1.png";
import shortestb1 from "./shortestb1.png";
import "antd-mobile/lib/switch/style/css";
import "./Options.scss";
export const displayModes = [
{
id: 0,
name: "2D",
bg: flat,
},
{
id: 1,
name: "3D",
bg: thrD,
},
];
export const searchTypes = [
{
id: 0,
name: "最佳",
bg: shortest,
bgb: shortestb,
bg1: shortest1,
bgb1: shortestb1,
},
{
id: 1,
name: "扶梯",
bg: ft,
bgb: ftb,
bg1: ft1,
bgb1: ftb1,
},
{
id: 2,
name: "直梯",
bg: zt,
bgb: ztb,
bg1: zt1,
bgb1: ztb1,
},
];
export const audioOptions = [
{
id: 0,
name: "语音",
bg: on,
},
{
id: 1,
name: "语音",
bg: mute,
},
];
const Options = ({
show,
hide,
onClickDisplayMode,
onClickSearchType,
onClickPlayAudioMode,
showHeadBar,
}) => (
<Modal
isOpen={show}
style={{
overlay: {
zIndex: 10000,
background: "rgba(0,0,0,0)",
},
}}
ariaHideApp={false}
className={"modal" + (showHeadBar ? " has-header-bar" : "")}
onRequestClose={() => hide()}
>
<div className="row">
{displayModes.map(({ id, name, bg }) => (
<div
key={id}
className={"col"}
onClick={() => {
onClickDisplayMode(id);
hide();
}}
>
<div
className="up"
style={{
background: `center/22px 22px no-repeat url(${bg})`,
}}
></div>
<div className="down">{name}</div>
</div>
))}
<div className="col"></div>
</div>
<div className="row">
{searchTypes.map(({ id, name, bg }) => (
<div
key={id}
className="col"
onClick={() => {
onClickSearchType(id);
hide();
}}
>
<div
className="up"
style={{
background: `center/22px 22px no-repeat url(${bg})`,
}}
></div>
<div className="down">{name}</div>
</div>
))}
</div>
</Modal>
);
export default Options;

106
src/components/Options/Options.scss

@ -1,106 +0,0 @@
.modal {
position: absolute;
width: 168px;
height: 136px;
background: #ffffff;
border-radius: 8px;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.08);
outline: none;
right: 59px;
top: 12px;
overflow: hidden;
padding-top: 16px;
&.has-header-bar {
top: 112px;
}
.title {
background: #f4f4f4;
padding: 0 19px;
color: #878787;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
line-height: 40px;
font-size: 11px;
}
.row {
display: flex;
flex: 1;
flex-direction: row;
margin-bottom: 18px;
.col {
flex: 1;
text-align: center;
.up {
width: 22px;
height: 22px;
margin: auto;
}
.down {
font-size: 12px;
font-family: SourceHanSansCN, SourceHanSansCN-Regular;
font-weight: 400;
text-align: center;
color: #696969;
line-height: 20px;
}
&.active {
.down {
color: #0074ed;
}
}
}
}
.bottom {
position: absolute;
bottom: 0;
width: 100%;
line-height: 52px;
padding: 0 20px;
background: #f4f4f4;
color: #404040;
font-size: 12px;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
.am-switch {
position: absolute;
top: 16px;
right: 20px;
input[type="checkbox"]:checked + .checkbox:after {
transform: translateX(22px);
}
.checkbox {
width: 42px;
height: 20px;
border-radius: 20px;
&:before {
content: " ";
position: absolute;
left: 1.5px;
top: 1.5px;
width: 39px;
height: 17px;
border-radius: 17px;
box-sizing: border-box;
background: #fff;
z-index: 1;
transition: all 200ms;
transform: scale(1);
}
&:after {
content: " ";
height: 17px;
width: 17px;
border-radius: 17px;
background: #fff;
position: absolute;
z-index: 2;
left: 1.5px;
top: 1.5px;
transform: translateX(0);
transition: all 200ms;
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.21);
}
}
}
}
}

BIN
src/components/Options/ft.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 720 B

BIN
src/components/Options/ft1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/components/Options/ftb.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

BIN
src/components/Options/ftb1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/components/Options/mute.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/components/Options/on.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/components/Options/shortest.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/components/Options/shortest1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/components/Options/shortestb.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

BIN
src/components/Options/shortestb1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/components/Options/zt.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

BIN
src/components/Options/zt1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

BIN
src/components/Options/ztb.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 466 B

BIN
src/components/Options/ztb1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

150
src/components/Popup/Popup.js

@ -1,64 +1,100 @@
import React from "react";
import desc from "./desc.png";
import closeButton from "./close.png";
import React, { useState, useEffect } from "react";
import "./Popup.scss"; import "./Popup.scss";
import navpng from "./nav.png";
import arpng from "./ar.png";
import couponTop from "./couponTop.png";
const Popup = ({
showPopup,
defaultPopup,
floors,
closePopup,
shop,
showDetail,
setEnd,
handleAR,
onClickCoupon,
}) => (
<div className={["popup-wrapper", showPopup ? "" : "noshow"].join(" ")}>
{floors}
{defaultPopup}
{showPopup && (
<div className="popup">
{shop.hasCoupon && (
<img
className="couponTop"
src={couponTop}
onClick={(shop) => onClickCoupon(shop)}
></img>
)}
<img
alt="关闭"
className="close-icon"
src={closeButton}
onClick={() => closePopup()}
></img>
<div className="r1">
{shop.logoPath && (
import ShopList from "../ShopList/ShopList.js";
const Popup = ({ mall, sceneIndex, onClick, floors, shop, onClickActive }) => {
const [long, setLong] = useState(false);
const [height, setHeight] = useState(false);
const [start, setStart] = useState(null);
const [doTransition, setdoTransition] = useState(false);
const baseHeight = long ? window.innerHeight : 312;
useEffect(() => {
setdoTransition(true);
setHeight(baseHeight);
setTimeout(() => {
setdoTransition(false);
}, 500);
}, [long]);
const handleTouchStart = (e) => {
if (start) return;
setStart({
identifier: e.changedTouches[0].identifier,
y: e.changedTouches[0].clientY,
});
};
const handleTouchMove = (e) => {
if (!start) return;
const touch = Array.from(e.changedTouches).find(
({ identifier }) => identifier === start.identifier
);
if (!touch) return;
const delta = touch.clientY - start.y;
setHeight(baseHeight - delta);
};
const handleTouchEnd = (e) => {
if (!start) return;
const touch = Array.from(e.changedTouches).find(
({ identifier }) => identifier === start.identifier
);
if (!touch) return;
setStart(null);
const delta = touch.clientY - start.y;
const nxtLong =
!long && delta < -100 ? true : long && delta > 100 ? false : long;
if (long === nxtLong) {
setdoTransition(true);
setHeight(baseHeight);
setTimeout(() => {
setdoTransition(false);
}, 500);
} else setLong(nxtLong);
};
useEffect(() => {
if (shop) {
if (long) {
setLong(false);
setTimeout(() => {
const domEl = document.getElementById("shop" + shop.houseNum);
if (domEl)
domEl.scrollIntoView({ behavior: "smooth", block: "center" });
}, 500);
} else {
const domEl = document.getElementById("shop" + shop.houseNum);
if (domEl)
domEl.scrollIntoView({ behavior: "smooth", block: "center" });
}
}
}, [shop]);
return (
<div <div
className="avatar"
className={["popup-wrapper", long ? "long" : ""].join(" ")}
style={{ style={{
backgroundImage: `url(${shop.logoPath})`,
height: height + "px",
transition: !doTransition ? "none" : "margin-bottom 0.5s ease",
backgroundImage: mall.theme.image.backgroundImg
? `url(${mall.theme.image.backgroundImg})`
: "",
}} }}
></div>
)}
<div style={{ flex: 1 }}>
<div className="popupname">{shop.name}</div>
<div className="popupdesc">
<span> {shop.shopFormat ? shop.shopFormat : " "}</span>
<span> {shop.floorName}</span>
</div>
</div>
</div>
<div className="tabs">
<div className="tab" onClick={() => setEnd()}>
<img src={navpng} /> 导航动画
</div>
</div>
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchCancel={handleTouchEnd}
onTouchEnd={handleTouchEnd}
>
{floors}
<div className="listWrapper">
<ShopList
className="flex1"
mall={mall}
isRow={false}
format={null}
floorOrder={sceneIndex}
onClick={onClick}
shop={shop}
onClickActive={onClickActive}
></ShopList>
</div> </div>
)}
</div> </div>
);
);
};
export default Popup; export default Popup;

195
src/components/Popup/Popup.scss

@ -3,196 +3,27 @@
width: 100vw; width: 100vw;
left: 0; left: 0;
bottom: 0; bottom: 0;
height: 312px;
z-index: 10000; z-index: 10000;
box-sizing: border-box; box-sizing: border-box;
&.noshow {
padding: 0;
}
.popup {
position: relative;
width: calc(100vw - 20px);
margin-left: 10px;
margin-bottom: 26px;
background: #ffffff;
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08);
border-radius: 18px;
height: 200px;
background: #fff;
.couponTop {
position: absolute;
left: 0;
right: 0;
top: -40px;
z-index: -1;
width: 100%;
object-fit: contain;
}
.close-icon {
position: absolute;
top: 16px;
right: 16px;
width: 24px;
height: 24px;
z-index: 10;
}
.r1 {
display: flex;
width: 100%;
padding: 14px 20px 0 14px;
height: 110px;
.avatar {
width: 80px;
height: 80px;
background: #ffffff;
box-shadow: 0px 8px 16px rgba(104, 110, 127, 0.08);
border-radius: 6px;
margin-right: 22px;
background-size: 64px 64px;
background-position: center;
background-repeat: no-repeat;
}
.popupname {
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 24px;
line-height: 34px;
color: #323337;
margin-top: 10px;
margin-bottom: 10px;
width: calc(100vw - 187px);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.popupdesc {
display: flex; display: flex;
align-items: center;
justify-content: space-between;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #a1a5b3;
}
}
.tabs {
position: relative;
display: flex;
padding: 20px 14px;
padding-bottom: 0;
&::after {
content: "";
position: absolute;
top: 0;
left: 20px;
right: 20px;
border-top: 1px dashed #edeff3;
}
.tab {
position: relative;
display: flex;
justify-content: center;
align-items: center;
flex: 1;
height: 56px;
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
border-radius: 10px;
text-align: center;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 22px;
color: #ffffff;
img {
width: 20px;
height: 20px;
margin-right: 8px;
}
}
.tab + .tab {
margin-left: 14px;
}
}
.meta {
line-height: 12px;
vertical-align: middle;
img {
width: 12px;
}
.title {
color: #7e7e7e;
font-size: 12px;
margin-left: 5px;
}
}
.detail {
color: #a9a9a9;
font-size: 12px;
line-height: 16px;
padding-right: 17px;
padding-bottom: 30px;
.title {
margin-bottom: 4px;
color: #7e7e7e;
font-size: 14px;
line-height: 14px;
}
.content {
max-height: 64px;
overflow: scroll;
}
}
.navbtn {
position: absolute;
top: 46px;
right: 14px;
text-align: center;
flex-direction: column;
background: var(--global-background);
&::before { &::before {
content: ""; content: "";
display: block;
position: absolute; position: absolute;
top: 9px;
width: 36px;
height: 4px;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
top: -10px;
left: 0; left: 0;
right: 0; right: 0;
margin: 0 auto;
width: 74px;
height: 30px;
background: linear-gradient(
90deg,
rgba(46, 177, 255, 1) 0%,
rgba(61, 140, 255, 1) 100%
);
border-radius: 17px;
opacity: 0.5;
filter: blur(4px);
z-index: -2;
}
&::after {
content: "去这里";
display: block;
top: 0;
right: 0;
z-index: 2;
background: linear-gradient(
90deg,
rgba(46, 177, 255, 1) 0%,
rgba(61, 140, 255, 1) 100%
);
border-radius: 17px;
line-height: 34px;
padding: 0 18px;
font-size: 12px;
font-family: SourceHanSansCN-Medium, SourceHanSansCN;
font-weight: 500;
color: #fff;
}
margin: auto;
} }
.listWrapper {
flex: 1;
overflow-x: hidden;
overflow-y: auto;
} }
} }

BIN
src/components/Popup/ar.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/components/Popup/close.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

BIN
src/components/Popup/couponTop.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

BIN
src/components/Popup/desc.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

BIN
src/components/Popup/nav.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

28
src/components/Shop/Shop.js

@ -1,17 +1,21 @@
import React from "react"; import React from "react";
import "./Shop.scss"; import "./Shop.scss";
import { LazyLoadImage } from "react-lazy-load-image-component"; import { LazyLoadImage } from "react-lazy-load-image-component";
import activeBg from "./active.png";
const Shop = ({ const Shop = ({
name, name,
floorName,
shopFormat, shopFormat,
floor,
hasBorderTop, hasBorderTop,
onClick, onClick,
logoPath, logoPath,
isRow, isRow,
houseNum, houseNum,
isActive,
onClickActive,
}) => ( }) => (
<div <div
id={"shop" + houseNum}
onClick={() => onClick()} onClick={() => onClick()}
className={ className={
"shop" + "shop" +
@ -19,19 +23,31 @@ const Shop = ({
(isRow ? " is-row" : "") (isRow ? " is-row" : "")
} }
> >
{isActive && !isRow && (
<div
className="active"
onClick={(e) => {
e.stopPropagation();
onClickActive();
}}
>
<img src={activeBg} className="avatar"></img>
<div className="r1">{name} </div>
</div>
)}
<LazyLoadImage className="avatar" src={logoPath}></LazyLoadImage> <LazyLoadImage className="avatar" src={logoPath}></LazyLoadImage>
{isRow ? ( {isRow ? (
<> <>
<div className="name">{name}</div> <div className="name">{name}</div>
<div className="format">{shopFormat}</div>
<div className="houseNum">{houseNum}</div>
<div className="meta">
{shopFormat} <div className="sep"></div>
{floor}
</div>
<div className="rowRight"></div>
</> </>
) : ( ) : (
<> <>
<div className="r1">{name} </div> <div className="r1">{name} </div>
<div className="r2">
{shopFormat} <span>{floorName}</span>
</div>
</> </>
)} )}
</div> </div>

117
src/components/Shop/Shop.scss

@ -1,91 +1,100 @@
/*postcss-pxtransform disable*/ /*postcss-pxtransform disable*/
.shop { .shop {
position: relative;
font-size: 0; font-size: 0;
line-height: 0; line-height: 0;
overflow: hidden; overflow: hidden;
background: var(--brand-background);
border-radius: 6px;
.active {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(99.5deg, #f0b92b 0%, #f9d556 100%);
.avatar {
display: block;
width: 100%;
height: calc((100vw - 55px) / 4);
padding: 8px;
background: #ffffff;
box-sizing: border-box;
border-radius: 4px;
}
.r1 {
color: rgba(0, 0, 0, 0.8);
}
}
&.is-row { &.is-row {
position: relative; position: relative;
height: 66px;
background: #ffffff;
height: 80px;
background: rgba(255, 255, 255, 0.6);
border-radius: 12px; border-radius: 12px;
.rowRight {
position: absolute;
right: 12px;
top: 0;
bottom: 0;
margin: auto;
width: 56px;
height: 44px;
background: center / cover no-repeat url(./rowRight.png);
}
.avatar { .avatar {
position: absolute; position: absolute;
width: 50px;
height: 50px;
width: 64px;
height: 64px;
top: 8px; top: 8px;
left: 8px; left: 8px;
border: 1px solid #e9d7ad;
box-sizing: border-box; box-sizing: border-box;
border-radius: 6px; border-radius: 6px;
padding: 7px;
} }
.name { .name {
position: absolute; position: absolute;
top: 10px;
left: 66px;
font-style: normal;
font-weight: bold;
top: 14px;
left: 92px;
font-weight: 600;
font-size: 16px; font-size: 16px;
line-height: 22px; line-height: 22px;
color: #333333;
}
.houseNum {
position: absolute;
left: 67px;
bottom: 13px;
font-style: normal;
font-weight: 500;
font-size: 10px;
line-height: 13px;
color: #b3aea7;
color: rgba(0, 0, 0, 0.8);
} }
.format {
.meta {
display: flex;
position: absolute; position: absolute;
top: 11px;
right: 16px;
font-style: normal;
font-weight: bold;
top: 49px;
left: 92px;
font-weight: 600;
font-size: 12px; font-size: 12px;
line-height: 17px; line-height: 17px;
color: #b3aea7;
color: rgba(0, 0, 0, 0.4);
align-items: center;
.sep {
display: inline-block;
margin: 0 12px;
width: 1px;
height: 10px;
background: rgba(0, 0, 0, 0.1);
}
} }
} }
.avatar { .avatar {
width: calc((100vw - 96px - 18px - 10px - 11px) / 3);
height: calc((100vw - 96px - 18px - 10px - 11px) / 3);
display: block;
width: 100%;
height: calc((100vw - 55px) / 4);
padding: 8px; padding: 8px;
background: #ffffff; background: #ffffff;
box-sizing: border-box; box-sizing: border-box;
border-radius: 6px;
border-radius: 4px;
} }
.r1 { .r1 {
padding: 0 4px;
margin-top: 4px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-weight: 600;
font-size: 12px; font-size: 12px;
line-height: 17px;
color: #323337;
line-height: 25px;
padding: 0 6px;
color: var(--brand-color, rgba(0, 0, 0, 0.8));
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.r2 {
margin-top: 4px;
display: flex;
justify-content: space-between;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 9px;
line-height: 13px;
color: #a1a5b3;
padding: 0 4px;
span {
font-weight: normal;
font-size: 10px;
color: #a1a5b3;
}
}
} }

BIN
src/components/Shop/active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/components/Shop/rowRight.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

27
src/components/ShopList/ShopList.js

@ -1,4 +1,4 @@
import React, { useState, useRef } from "react";
import React, { useState, useRef, useEffect } from "react";
import Shop from "../Shop/Shop"; import Shop from "../Shop/Shop";
import "./ShopList.scss"; import "./ShopList.scss";
import InfiniteScroll from "react-infinite-scroller"; import InfiniteScroll from "react-infinite-scroller";
@ -7,10 +7,11 @@ const ShopList = ({
mall, mall,
q, q,
onClick, onClick,
top,
isRow = false, isRow = false,
format = null, format = null,
floorOrder = null, floorOrder = null,
shop: activeShop,
onClickActive,
}) => { }) => {
const [index, setIndex] = useState(0); const [index, setIndex] = useState(0);
const shops = mall.shopInfo.reduce( const shops = mall.shopInfo.reduce(
@ -52,7 +53,12 @@ const ShopList = ({
(format === null ? true : shopFormat === format) && (format === null ? true : shopFormat === format) &&
(floorOrder === null ? true : floorOrder1 === floorOrder) (floorOrder === null ? true : floorOrder1 === floorOrder)
); );
const formatMap = filteredShops.reduce((acc, nxt) => {
if (!acc[nxt.shopFormat]) return { ...acc, [nxt.shopFormat]: 1 };
return { ...acc, [nxt.shopFormat]: acc[nxt.shopFormat] + 1 };
}, {});
const listRef = useRef(null); const listRef = useRef(null);
return ( return (
<div className={"shop-list " + (isRow ? "is-row" : "")} ref={listRef}> <div className={"shop-list " + (isRow ? "is-row" : "")} ref={listRef}>
<InfiniteScroll <InfiniteScroll
@ -64,13 +70,30 @@ const ShopList = ({
> >
<div className="list"> <div className="list">
{filteredShops.map((shop, i) => ( {filteredShops.map((shop, i) => (
<>
{(i === 0 ||
filteredShops[i - 1].shopFormat !== shop.shopFormat) &&
!isRow && (
<div
className="format"
key={`${shop.shopFormat}_${shop.houseNum}`}
>
{shop.shopFormat}
<span className="meta">
/{formatMap[shop.shopFormat]}
</span>
</div>
)}
<Shop <Shop
{...shop} {...shop}
hasBorderTop={i !== 0} hasBorderTop={i !== 0}
key={`${shop.name}_${shop.houseNum}`} key={`${shop.name}_${shop.houseNum}`}
onClick={() => onClick(shop)} onClick={() => onClick(shop)}
isRow={isRow} isRow={isRow}
isActive={activeShop && shop.houseNum === activeShop.houseNum}
onClickActive={() => onClickActive(shop)}
></Shop> ></Shop>
</>
))} ))}
</div> </div>
<div className="end">END</div> <div className="end">END</div>

36
src/components/ShopList/ShopList.scss

@ -2,7 +2,7 @@
width: 100%; width: 100%;
padding: 0 10px; padding: 0 10px;
&.is-row { &.is-row {
padding: 0 8px;
padding: 0 14px;
.list { .list {
display: grid; display: grid;
gap: 8px; gap: 8px;
@ -11,29 +11,21 @@
} }
.list { .list {
display: grid; display: grid;
gap: 12px 9px;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px 9px;
grid-template-columns: 1fr 1fr 1fr 1fr;
padding: 10px 0; padding: 10px 0;
.format {
grid-column: 1 / 5;
font-weight: 600;
font-size: 24px;
line-height: 34px;
color: var(--brand-floorNameColor);
.meta {
font-weight: 600;
font-size: 14px;
line-height: 20px;
color: var(--brand-floorMetaColor);
} }
.search-his {
position: relative;
padding: 0 14px 0 15px;
color: #5a5a5a;
font-weight: 400;
font-size: 12px;
line-height: 45px;
background: #fff;
.button {
float: right;
color: #4d9fdd;
}
&::after {
content: "";
position: absolute;
display: block;
width: calc(100vw - 29px);
bottom: 0;
border-top: 1px solid #f7f7f7;
} }
} }
.end { .end {

24
src/components/ShopTabs/ShopTabs.js

@ -1,24 +0,0 @@
import React from "react";
import "./ShopTabs.scss";
import floor from "./floor.png";
import floorActive from "./floor_active.png";
import format from "./format.png";
import formatActive from "./format_active.png";
export default ({ tab, onSetTab }) => (
<div className="shop-tabs">
<div
onClick={() => onSetTab("业态")}
className={["tab", tab === "业态" ? "active" : ""].join(" ")}
>
<img src={tab === "业态" ? formatActive : format}></img>
业态
</div>
<div
onClick={() => onSetTab("楼层")}
className={["tab", tab === "楼层" ? "active" : ""].join(" ")}
>
<img src={tab === "楼层" ? floorActive : floor}></img>
楼层
</div>
</div>
);

32
src/components/ShopTabs/ShopTabs.scss

@ -1,32 +0,0 @@
.shop-tabs {
display: flex;
width: calc(100vw - 20px);
height: 56px;
background: #edeff3;
border-radius: 12px;
justify-content: space-around;
align-items: center;
.tab {
display: flex;
width: calc((100vw - 20px - 8px - 3px) / 2);
height: 48px;
justify-content: center;
align-items: center;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 22px;
color: #7a7e8d;
&.active {
background: #ffffff;
border-radius: 8px;
color: #323337;
}
img {
width: 20px;
height: 20px;
margin-right: 8px;
}
}
}

BIN
src/components/ShopTabs/floor.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 901 B

BIN
src/components/ShopTabs/floor_active.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

BIN
src/components/ShopTabs/format.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/components/ShopTabs/format_active.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

103
src/components/ShopsWithFilter/ShopsWithFilter.js

@ -1,103 +0,0 @@
import React, { useState, useEffect } from "react";
import ShopList from "../ShopList/ShopList.js";
import "./ShopsWithFilter.scss";
import ShopTabs from "../ShopTabs/ShopTabs";
import SideBar from "../SideBar/SideBar";
const ShopsWithFilter = ({
mall,
onClick,
reset,
onReset = () => {},
wingHeight,
}) => {
const [tab, setTab] = useState("业态");
const [format, setFormat] = useState(null);
const [floorOrder, setFloorOrder] = useState(null);
useEffect(() => {
if (reset) {
setFormat(null);
setFloorOrder(null);
setTab("业态");
onReset();
}
}, [reset]);
const formats = mall
? mall.shopInfo.reduce(
(acc, { shopList }) =>
shopList.reduce(
(acc1, nxt) =>
acc1.includes(nxt.shopFormat)
? [...acc1]
: [...acc1, nxt.shopFormat],
acc
),
[]
)
: [];
const floors = mall ? mall.floorData : [];
const floorNameOrderMap = floors.reduce(
(acc, nxt) => ({ ...acc, [nxt.name]: nxt.floorOrder }),
{}
);
const floorOrderNameMap = floors.reduce(
(acc, nxt) => ({ ...acc, [nxt.floorOrder]: nxt.name }),
{}
);
return (
<>
<div style={{ marginTop: "16px", marginLeft: "10px" }}>
<ShopTabs
tab={tab}
onSetTab={(el) => {
setFormat(null);
setFloorOrder(null);
setTab(el);
}}
></ShopTabs>
</div>
<div className="wings" style={{ height: wingHeight }}>
<div className="left">
<SideBar
active={
tab === "业态" && format === null
? "全部业态"
: tab === "楼层" && floorOrder === null
? "全部楼层"
: tab === "业态"
? format
: floorOrderNameMap[floorOrder]
}
onSetActive={(el) => {
if (tab === "业态") {
setFormat(el === "全部业态" ? null : el);
} else {
setFloorOrder(el === "全部楼层" ? null : floorNameOrderMap[el]);
}
}}
list={
tab === "业态"
? ["全部业态", ...formats]
: [
"全部楼层",
...floors
.filter(({ url }) => url !== null)
.map(({ name }) => name),
]
}
></SideBar>
</div>
<div className="right">
<ShopList
mall={mall}
isRow={false}
format={format}
floorOrder={floorOrder}
onClick={onClick}
></ShopList>
</div>
</div>
</>
);
};
export default ShopsWithFilter;

22
src/components/ShopsWithFilter/ShopsWithFilter.scss

@ -1,22 +0,0 @@
.wings {
display: flex;
width: 100vw;
height: calc(100vh - 156px);
border-top: 1px solid #edeff3;
margin-top: 8px;
.left {
width: 96px;
flex: 0 0 96px;
height: 100%;
background: #edeff3;
overflow-x: hidden;
overflow-y: auto;
}
.right {
flex: 1;
height: 100%;
background: #f3f4f8;
overflow-x: hidden;
overflow-y: auto;
}
}

15
src/components/SideBar/SideBar.js

@ -1,15 +0,0 @@
import React from "react";
import "./SideBar.scss";
export default ({ list, active, onSetActive }) => (
<div className="side-bar">
{list.map((el) => (
<div
key={el}
className={["option", active === el ? "active" : ""].join(" ")}
onClick={() => onSetActive(el)}
>
{el}
</div>
))}
</div>
);

20
src/components/SideBar/SideBar.scss

@ -1,20 +0,0 @@
.side-bar {
width: 100%;
.option {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 48px;
font-family: PingFang SC;
font-style: normal;
font-weight: 500;
font-size: 12px;
color: #474a56;
&.active {
background: #ffffff;
color: #437af7;
font-weight: 600;
}
}
}

28
src/js/helpers/data-helper.js

@ -40,7 +40,7 @@ const getMallInfo = async () => {
shopInfoUrl: `${baseUrl}/api/guide/v1/web/getMapInfo?projectCode=${code}`, shopInfoUrl: `${baseUrl}/api/guide/v1/web/getMapInfo?projectCode=${code}`,
}; };
const [cdnUrl, mapDataJSON, [buildingList, serverShopInfo], facs] =
const [cdnUrl, mapDataJSON, [buildingList, serverShopInfo], facs, theme] =
await Promise.all([ await Promise.all([
(async () => { (async () => {
try { try {
@ -92,6 +92,19 @@ const getMallInfo = async () => {
return []; return [];
} }
})(), })(),
(async () => {
try {
const {
data: { data: theme },
} = await axios.get(
`${baseUrl}/api/guide/v1/web/getProjectBindingTheme?projectCode=${code}`
);
return theme;
} catch (error) {
console.error(error);
return {};
}
})(),
]); ]);
const mapData = JSON.parse(mapDataJSON)[0]; const mapData = JSON.parse(mapDataJSON)[0];
mall.floors = buildingList[0].floorList.map(({ floor, floorOrder }) => ({ mall.floors = buildingList[0].floorList.map(({ floor, floorOrder }) => ({
@ -122,7 +135,7 @@ const getMallInfo = async () => {
return acc; return acc;
}, []) }, [])
.map((shopList, floorOrder) => ({ floorOrder, shopList })); .map((shopList, floorOrder) => ({ floorOrder, shopList }));
console.log(shopInfo);
shopInfo.forEach(({ shopList }) => shopInfo.forEach(({ shopList }) =>
shopList.forEach((shop) => { shopList.forEach((shop) => {
shop.initialsCn = shop.name shop.initialsCn = shop.name
@ -150,7 +163,15 @@ const getMallInfo = async () => {
mapData.buildArr.forEach(({ mapData: { parkArea } }) => { mapData.buildArr.forEach(({ mapData: { parkArea } }) => {
parkArea.forEach(({ parkNum }) => mall.lots.push(parkNum)); parkArea.forEach(({ parkNum }) => mall.lots.push(parkNum));
}); });
console.log(mapData);
const r = document.querySelector(":root");
Object.entries(theme).forEach(([cat, obj]) => {
Object.entries(obj).forEach(([k, v]) => {
if (cat === "image") theme[cat][k] = cdnUrl + v;
else r.style.setProperty(`--${cat}-${k}`, v);
});
});
console.log(mapData, shopInfo, theme);
Object.assign(mall, { Object.assign(mall, {
floorData: mall.floors, floorData: mall.floors,
shopInfo, shopInfo,
@ -159,6 +180,7 @@ const getMallInfo = async () => {
acc[floorOrder] = [url, name]; acc[floorOrder] = [url, name];
return acc; return acc;
}, new Array()), }, new Array()),
theme,
}); });
const mallInfo = { mall, shopInfo, images }; const mallInfo = { mall, shopInfo, images };
mallInfos.set(mall.code, mallInfo); mallInfos.set(mall.code, mallInfo);

212
src/pages/Car/Car.js

@ -1,212 +0,0 @@
import React, { useState, useEffect } from "react";
import car from "./car.png";
import axios from "axios";
import "./Car.scss";
import plus from "./plus.svg";
import Keyboard from "../Keyboard/Keyboard";
import platepng from "./plate.png";
import plateActive from "./plate_active.png";
import lot from "./lot.png";
import lotActive from "./lot_active.png";
const Car = ({ lots, onLot = () => {}, plate, hasReverse }) => {
const [isPlate, setIsPlate] = useState(hasReverse);
const [qArr, setQArr] = useState(hasReverse ? ["苏", "A"] : []);
const [opened, setOpened] = useState(false);
const [showKeyBoard, setShowKeyBoard] = useState(true);
const [focusedIndex, setFocusedIndex] = useState(hasReverse ? 2 : 0);
const [isNum, setIsNum] = useState(true);
const q = qArr.join("");
const setQ = (str) => setQArr(str.split(""));
useEffect(() => {
if (!opened) {
setOpened(true);
if (plate) {
setQ(plate);
setFocusedIndex(null);
}
setShowKeyBoard(!plate);
}
}, [opened]);
const toPlate = () => {
if (!hasReverse)
return window.weui.toast("敬请期待", {
className: "toast",
});
setQ("苏A");
setIsPlate(true);
setFocusedIndex(2);
setShowKeyBoard(true);
};
const toLot = () => {
setQ("");
setFocusedIndex(0);
setIsPlate(false);
setShowKeyBoard(true);
};
const handleSubmit = async () => {
if (isPlate) {
if (!q) {
return window.weui.toast("请输入正确车牌号", {
className: "toast",
});
}
const {
data: { data, code, msg },
} = { data: { data: null, code: "201", msg: "123" } };
if (code !== "200")
return window.weui.toast(msg, {
className: "toast",
});
else {
if (!lots.includes(data.spaceNo))
return window.weui.toast(`未找到车位号:${data.spaceNo}`, {
className: "toast",
});
return onLot(data.spaceNo);
}
}
// if (!q || !lots.includes(floor + q.toUpperCase())) {
if (!q || !lots.includes(q.toUpperCase())) {
return window.weui.toast("请输入正确车位号", {
className: "toast",
});
}
// onLot(floor + q.toUpperCase());
onLot(q.toUpperCase());
};
return (
<div className="car">
<img className="car-img" src={car} />
<div className="car-modal">
<div className={"content" + (showKeyBoard ? " has-keyboard" : "")}>
<div className="form">
<div className="tabs">
<div
className={`tab ${isPlate ? "active" : ""}`}
onClick={toPlate}
>
<img src={isPlate ? plateActive : platepng}></img>
车牌查找
</div>
<div
className={`tab ${!isPlate ? "active" : ""}`}
onClick={toLot}
>
<img src={isPlate ? lot : lotActive}></img>
车位查找
</div>
</div>
{isPlate ? (
<div className="platenum">
{new Array(8).fill(0).map((_, i) => (
<div
className={[
"box",
focusedIndex === i ? "active" : "",
i === 2 ? "more-margin" : "",
i === 7 ? "sp" : "",
].join(" ")}
key={i}
onClick={() => {
setIsNum(i !== 0);
setFocusedIndex(i);
setShowKeyBoard(true);
}}
>
{i === 7 && !qArr[i] ? (
<>
<img src={plus} className="plus"></img>
</>
) : (
qArr[i]
)}
</div>
))}
</div>
) : (
<div className="lots">
{new Array(4).fill(0).map((_, i) => (
<div
className={[
"box",
"big",
focusedIndex === i ? "active" : "",
].join(" ")}
key={i}
onClick={() => {
setIsNum(true);
setFocusedIndex(i);
setShowKeyBoard(true);
}}
>
{qArr[i]}
</div>
))}
</div>
)}
{!isPlate && (
<>
{/* <div className="floor1" onClick={() => setFloor(floor1)}>
{floor1}
</div>
<div className="floor2">{floor}</div>
<div className="floor3" onClick={() => setFloor(floor3)}>
{floor3}
</div> */}
</>
)}
<div className="btn" onClick={handleSubmit}>
寻车
</div>
</div>
</div>
</div>
{showKeyBoard && (
<Keyboard
isNum={isNum}
onClose={() => {
setFocusedIndex(null);
setShowKeyBoard(false);
}}
onSetIsNum={(val) => setIsNum(val)}
onInput={(val) => {
qArr[focusedIndex] = val;
setQArr([...qArr]);
if (isPlate) {
switch (focusedIndex) {
case 6:
case 7:
setShowKeyBoard(false);
break;
default:
setIsNum(true);
setFocusedIndex(focusedIndex + 1);
break;
}
} else {
switch (focusedIndex) {
case 3:
setShowKeyBoard(false);
break;
default:
setIsNum(true);
setFocusedIndex(focusedIndex + 1);
break;
}
}
}}
onBackspace={() => {
qArr[focusedIndex] = "";
setQArr([...qArr]);
setFocusedIndex(Math.max(0, focusedIndex - 1));
}}
onFinish={handleSubmit}
></Keyboard>
)}
</div>
);
};
export default Car;

255
src/pages/Car/Car.scss

@ -1,255 +0,0 @@
.car {
position: relative;
width: 100vw;
height: calc(100vh - 98px);
background: #f3f4f8;
pointer-events: auto;
.car-img {
position: absolute;
width: 220px;
height: 220px;
left: 0;
right: 0;
bottom: auto;
margin: auto;
top: 16px;
}
.car-modal {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
}
.content {
position: absolute;
left: 2.6667vw;
right: 2.6667vw;
width: calc(100vw - 4.2667vw);
height: 458px;
bottom: 10px;
padding-top: 34px;
background: #ffffff;
box-shadow: 0px 12px 16px rgba(104, 110, 127, 0.08);
border-radius: 18px;
overflow: hidden;
.form {
position: absolute;
top: 14px;
left: 3.7333vw;
right: 3.7333vw;
bottom: 14px;
z-index: 3;
text-align: left;
.platenum {
display: flex;
justify-content: center;
position: absolute;
top: 102px;
left: -3.7333vw;
right: -3.7333vw;
text-align: center;
}
.lots {
position: absolute;
top: 95px;
left: 0;
right: 0;
display: inline-flex;
justify-content: center;
}
.box {
width: 9.6vw;
height: 64px;
background: #f3f4f8;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: bold;
font-size: 18px;
text-align: center;
color: #323337;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-direction: column;
&.big {
width: 12.8vw;
}
&.active {
border: 2px solid #437af7;
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2);
}
&.sp {
background: none;
border: 1px solid #c9cbd1;
&.active {
border: 2px solid #437af7;
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2);
}
}
.plus {
position: relative;
width: 6.4vw;
margin: 0;
}
}
.box + .box {
margin-left: 1.0667vw;
}
.box + .box.more-margin {
margin-left: 5.0667vw;
}
.input {
position: absolute;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: bold;
font-size: 16px;
top: 114px;
width: 216px;
left: calc((100vw - 28px - 216px) / 2);
background: transparent;
height: 40px;
line-height: 40px;
color: #474747;
border: none;
outline: none;
text-align: center;
&.right {
text-align: left;
left: calc((100vw - 28px - 216px + 63px) / 2);
}
}
::placeholder {
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: normal;
font-size: 14px;
color: #b3aea7;
}
.dec1 {
position: absolute;
top: 154px;
bottom: auto;
right: auto;
width: 223px;
height: 21px;
left: calc((100vw - 28px - 216px) / 2);
&.right {
left: calc((100vw - 28px - 216px + 63px) / 2);
}
}
.dec2 {
position: absolute;
top: 132px;
bottom: auto;
right: auto;
width: 11.7333vw;
height: 21px;
left: calc((100vw - 7.4667vw - 57.6vw - 16.8vw) / 2);
pointer-events: none;
}
.floor1,
.floor2,
.floor3 {
position: absolute;
left: calc((100vw - 7.4667vw - 57.6vw - 16.8vw) / 2);
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: bold;
font-size: 4.2667vw;
color: #474747;
width: 9.8667vw;
text-align: center;
}
.floor1,
.floor3 {
color: rgba(113, 112, 110, 0.2);
font-size: 3.2vw;
line-height: 4.8vw;
height: 4.8vw;
}
.floor1 {
top: 77px;
}
.floor2 {
top: 101px;
line-height: 6.4vw;
height: 6.4vw;
}
.floor3 {
top: 134px;
}
.btns {
display: grid;
grid-template-columns: 1fr 1fr;
position: absolute;
top: 129px;
left: 24px;
right: 24px;
gap: 0 16px;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
height: 56px;
left: 1.0667vw;
right: 1.0667vw;
margin: auto;
bottom: 14px;
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
box-shadow: 0px 6px 12px rgba(93, 172, 249, 0.2);
border-radius: 16px;
font-family: PingFang SC;
font-style: normal;
font-weight: bold;
font-size: 16px;
line-height: 22px;
text-align: center;
color: #ffffff;
}
.tabs {
display: flex;
width: 100%;
padding: 4px;
background: #edeff3;
border-radius: 12px;
}
.tab {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
height: 48px;
font-family: PingFang SC;
font-style: normal;
font-weight: bold;
font-size: 16px;
line-height: 22px;
color: #7a7e8d;
img {
position: relative;
margin: 0;
margin-right: 8px;
width: 24px;
height: 24px;
}
}
.tab.active {
background: #ffffff;
border-radius: 10px;
color: #323337;
}
.tab + .tab {
margin-left: 4px;
}
}
}
}

BIN
src/pages/Car/back.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/pages/Car/car.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
src/pages/Car/lot.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 B

BIN
src/pages/Car/lot_active.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 675 B

BIN
src/pages/Car/plate.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

BIN
src/pages/Car/plate_active.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

4
src/pages/Car/plus.svg

@ -1,4 +0,0 @@
<svg width="24" height="33" viewBox="0 0 24 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.2523 8.824H12.7563V12.104H16.0363V13.608H12.7563V16.904H11.2523V13.608H7.95625V12.104H11.2523V8.824Z" fill="#7A7E8D"/>
<path d="M7.512 24.176C6.83467 24.4107 6.07467 24.5573 5.232 24.616V25.912H7.712V26.64H6.936V30.832H6.192V26.64H5.232V27.448C5.19467 28.8507 4.88267 29.9733 4.296 30.816L3.76 30.24C4.21867 29.5627 4.464 28.632 4.496 27.448V23.992C5.46133 23.976 6.344 23.8133 7.144 23.504L7.512 24.176ZM0.464 24.072H1.896C1.77867 23.8427 1.664 23.6453 1.552 23.48L2.336 23.352C2.45333 23.592 2.55467 23.832 2.64 24.072H4.12V24.776H0.464V24.072ZM0.384 25.888H1.232C1.12533 25.6 1.00533 25.3387 0.872 25.104L1.536 24.856C1.68 25.176 1.80267 25.52 1.904 25.888H2.664C2.792 25.5467 2.904 25.2 3 24.848L3.68 25.088C3.58933 25.36 3.48 25.6267 3.352 25.888H4.168V26.584H2.688V27.304H4.032V27.992H2.688V30.128C2.688 30.6133 2.424 30.856 1.896 30.856H1.48L1.312 30.152C1.43467 30.184 1.54667 30.2 1.648 30.2C1.84 30.2 1.936 30.1147 1.936 29.944V27.992H0.512V27.304H1.936V26.584H0.384V25.888ZM1.68 28.488C1.48267 29.3093 1.21333 30.0133 0.872 30.6L0.248 30.2C0.6 29.6293 0.848 29.0107 0.992 28.344L1.68 28.488ZM3.496 28.288C3.71467 28.8213 3.88 29.2853 3.992 29.68L3.352 29.92C3.224 29.424 3.064 28.936 2.872 28.456L3.496 28.288ZM9.528 28.128V28.712H11.192V28.128H9.528ZM11.192 27.504V26.888H9.528V27.504H11.192ZM9.528 29.344V30.84H8.792V26.232H11.928V29.952C11.928 30.5067 11.6693 30.784 11.152 30.784H10.52L10.336 30.072L10.904 30.104C11.096 30.104 11.192 30 11.192 29.792V29.344H9.528ZM13.344 26.976C12.784 26.976 12.504 26.6693 12.504 26.056V23.464H13.256V24.416C14.1253 24.2827 14.8 24.1493 15.28 24.016L15.528 24.688C14.8453 24.848 14.088 24.9893 13.256 25.112V25.896C13.256 26.1627 13.3547 26.296 13.552 26.296H14.504C14.632 26.296 14.7227 26.256 14.776 26.176C14.8453 26.0693 14.888 25.8 14.904 25.368L15.616 25.6C15.552 26.2613 15.4453 26.6587 15.296 26.792C15.1467 26.9147 14.9307 26.976 14.648 26.976H13.344ZM13.264 29.8C13.264 29.9493 13.3573 30.024 13.544 30.024H14.504C14.6267 30.024 14.7173 29.9867 14.776 29.912C14.8453 29.8107 14.8907 29.5387 14.912 29.096L15.608 29.312C15.544 29.984 15.4373 30.3867 15.288 30.52C15.1493 30.6427 14.936 30.704 14.648 30.704H13.336C12.7867 30.704 12.512 30.456 12.512 29.96V27.264H13.264V28.144C13.9893 28.0693 14.6613 27.9387 15.28 27.752L15.528 28.432C14.856 28.6133 14.1013 28.7467 13.264 28.832V29.8ZM11.344 24C11.8027 24.6133 12.1653 25.1627 12.432 25.648L11.808 26.096C11.7173 25.9147 11.6293 25.7493 11.544 25.6C10.712 25.728 9.712 25.824 8.544 25.888L8.336 25.256C8.46933 25.208 8.584 25.144 8.68 25.064C9.176 24.5147 9.54933 23.9707 9.8 23.432L10.528 23.648C10.1973 24.2933 9.82133 24.8187 9.4 25.224C9.88533 25.1973 10.4907 25.1387 11.216 25.048C11.0987 24.8613 10.9467 24.6347 10.76 24.368L11.344 24ZM16.984 23.568C17.544 23.9787 18.0213 24.384 18.416 24.784L17.896 25.296C17.5813 24.9387 17.1067 24.5253 16.472 24.056L16.984 23.568ZM16.84 25.528C17.352 25.9067 17.7947 26.296 18.168 26.696L17.656 27.216C17.3413 26.8427 16.8987 26.4427 16.328 26.016L16.84 25.528ZM18.272 27.968C17.9147 28.9973 17.528 29.9413 17.112 30.8L16.4 30.488C16.88 29.576 17.2853 28.6507 17.616 27.712L18.272 27.968ZM19.832 25H20.928C20.9973 24.8027 21.056 24.5973 21.104 24.384H19.384V26.48C19.352 28.2827 19.048 29.7333 18.472 30.832L17.896 30.32C18.3813 29.3973 18.6347 28.1173 18.656 26.48V23.712H23.544V24.384H21.824C21.7707 24.6187 21.712 24.824 21.648 25H23.144V27.92H21.864V30.048C21.864 30.5493 21.6267 30.8 21.152 30.8H20.48L20.32 30.112C20.5227 30.144 20.7173 30.16 20.904 30.16C21.064 30.16 21.144 30.064 21.144 29.872V27.92H19.832V25ZM22.48 27.32V26.736H20.496V27.32H22.48ZM20.496 26.184H22.48V25.584H20.496V26.184ZM20.632 28.552C20.4453 29.2613 20.168 29.88 19.8 30.408L19.192 30.024C19.5493 29.5333 19.8053 28.9947 19.96 28.408L20.632 28.552ZM22.872 28.368C23.192 28.9387 23.4587 29.5227 23.672 30.12L23.032 30.4C22.7973 29.728 22.5333 29.1227 22.24 28.584L22.872 28.368Z" fill="#7A7E8D"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

277
src/pages/Index/Index.js

@ -4,7 +4,6 @@ import { useHistory, useLocation } from "react-router-dom";
import { getMallInfo } from "../../js/helpers/data-helper"; import { getMallInfo } from "../../js/helpers/data-helper";
import "./Index.scss"; import "./Index.scss";
import Floors from "../../components/Floors/Floors"; import Floors from "../../components/Floors/Floors";
import HeadBar from "../../components/HeadBar/HeadBar";
import Popup from "../../components/Popup/Popup"; import Popup from "../../components/Popup/Popup";
import pos from "./pos.png"; import pos from "./pos.png";
import offline from "./offline.png"; import offline from "./offline.png";
@ -12,17 +11,10 @@ import compass from "./compass.png";
import Shops from "../Shops/Shops"; import Shops from "../Shops/Shops";
import NavBottom from "../../components/NavBottom/NavBottom"; import NavBottom from "../../components/NavBottom/NavBottom";
import Modal from "react-modal"; import Modal from "react-modal";
import DefaultPopup, {
DefaultPopupStates,
} from "../../components/DefaultPopup/DefaultPopup";
import More from "../../components/More/More";
import arpng from "./ar.png";
export const MallCode = React.createContext(null); export const MallCode = React.createContext(null);
// const vConsole = new window.VConsole(); // const vConsole = new window.VConsole();
let focusdDevice; let focusdDevice;
let memberID;
let isShop;
const Index = () => { const Index = () => {
const history = useHistory(); const history = useHistory();
@ -38,51 +30,19 @@ const Index = () => {
const [mallCode, setMallCode] = useState(null); const [mallCode, setMallCode] = useState(null);
const startParams = params.get("s"); const startParams = params.get("s");
let endId = params.get("e"); let endId = params.get("e");
const openid = params.get("openid");
if (params.get("memberID")) memberID = params.get("memberID");
if (params.get("isShop")) isShop = params.get("isShop");
const plate = params.get("plate");
const [navigation, setNavigation] = useState(false); const [navigation, setNavigation] = useState(false);
const [inAnimation, setInAnimation] = useState(false); const [inAnimation, setInAnimation] = useState(false);
const [displayMode, setDisplayMode] = useState(1);
const [searchType, setSearchType] = useState(0);
const [showOptions, setShowOptions] = useState(false);
const [showShops, setShowShops] = useState(false); const [showShops, setShowShops] = useState(false);
const [routeSearchText, setRouteSearchText] = useState(""); const [routeSearchText, setRouteSearchText] = useState("");
const [percent, setPercent] = useState(0); const [percent, setPercent] = useState(0);
const [elevations, setElevations] = useState([]); const [elevations, setElevations] = useState([]);
const [paused, setPaused] = useState(false); const [paused, setPaused] = useState(false);
const [playAudio, setPlayAudio] = useState(false);
const [online, setOnline] = useState(true); const [online, setOnline] = useState(true);
const [azimuthAngle, setAzimuthAngle] = useState(0); const [azimuthAngle, setAzimuthAngle] = useState(0);
const [follow, setFollow] = useState(false); const [follow, setFollow] = useState(false);
const [facilities, setFacilities] = useState(null);
const [defaultPopupState, setDefaultPopupState] = useState(
DefaultPopupStates.init
);
const [start, _setStart] = useState(null); const [start, _setStart] = useState(null);
const [end, _setEnd] = useState(null); const [end, _setEnd] = useState(null);
const [isPick, _setIsPick] = useState(false);
const [doFocus, _setDoFocus] = useState(0); const [doFocus, _setDoFocus] = useState(0);
const [showARPrompt, setShowARPrompt] = useState(false);
const [ARshop, setARShop] = useState(null);
const [isTyping, setIsTyping] = useState(null);
const [showFindCar, setShowFindCar] = useState(false);
useEffect(() => {
if (shop) {
const e = shop.houseNum
? shop.houseNum
: shop.isDevice
? `${shop.floorOrder}_${shop.navPoint}_${shop.name}`
: encodeURIComponent(shop.id);
history.replace(
`/?openid=${openid}&e=${e}&name=${shop.name}${
shop.floorName ? "(" + shop.floorName + ")" : ""
}`
);
}
}, [shop]);
useEffect(() => { useEffect(() => {
if (!map) return; if (!map) return;
@ -105,7 +65,6 @@ const Index = () => {
} }
} }
if (!endId) return; if (!endId) return;
if (endId === "findcar") return setShowFindCar(true);
if (mall.mcShopIDHouseNumMap && mall.mcShopIDHouseNumMap[endId]) if (mall.mcShopIDHouseNumMap && mall.mcShopIDHouseNumMap[endId])
endId = mall.mcShopIDHouseNumMap[endId]; endId = mall.mcShopIDHouseNumMap[endId];
@ -176,12 +135,6 @@ const Index = () => {
_setEnd(data); _setEnd(data);
}; };
const isPickRef = useRef(isPick);
const setIsPick = (data) => {
isPickRef.current = data;
_setIsPick(data);
};
useEffect(() => { useEffect(() => {
let offlineListener = () => setOnline(false); let offlineListener = () => setOnline(false);
let onlineListener = () => setOnline(true); let onlineListener = () => setOnline(true);
@ -193,6 +146,18 @@ const Index = () => {
}; };
}); });
useEffect(() => {
const end = endRef.current;
if (!inAnimation && map && end) {
setShop(end);
const timeout = setTimeout(() => {
map.focusShopByHouseNum(end.houseNum);
}, 500);
exitFromNav();
return () => clearTimeout(timeout);
}
}, [inAnimation]);
const [_, dispatchLS] = useReducer( const [_, dispatchLS] = useReducer(
({ lastSearch }, { type, data }) => { ({ lastSearch }, { type, data }) => {
switch (type) { switch (type) {
@ -216,7 +181,6 @@ const Index = () => {
const handleFocus = ({ data, preventDefault }) => { const handleFocus = ({ data, preventDefault }) => {
const start = startRef.current; const start = startRef.current;
const end = endRef.current; const end = endRef.current;
const isPick = isPickRef.current;
const doFocus = doFocusRef.current; const doFocus = doFocusRef.current;
if (doFocus === 2) { if (doFocus === 2) {
setDoFocus(1); setDoFocus(1);
@ -225,8 +189,6 @@ const Index = () => {
} }
if (start && end) { if (start && end) {
preventDefault(); preventDefault();
} else if (((start && !end) || (!start && end)) && !isPick) {
preventDefault();
} else { } else {
if (follow) { if (follow) {
map.setFollow(false); map.setFollow(false);
@ -237,13 +199,6 @@ const Index = () => {
setDoFocus(0); setDoFocus(0);
}; };
const swap = async () => {
if (navigation && start && end) await navigation.stop();
if (start && end) map.startNavigate({ start: end, end: start });
setStart(end);
setEnd(start);
};
const handleBlur = () => { const handleBlur = () => {
if (focusdDevice) { if (focusdDevice) {
focusdDevice.blur(); focusdDevice.blur();
@ -251,7 +206,7 @@ const Index = () => {
} }
const doFocus = doFocusRef.current; const doFocus = doFocusRef.current;
if (doFocus === 1) return; if (doFocus === 1) return;
history.replace(`/?openid=${openid}`);
history.replace(`/`);
setShop(null); setShop(null);
}; };
@ -269,7 +224,7 @@ const Index = () => {
routeSearchAnimationType: 2, routeSearchAnimationType: 2,
routeSearchZoom: 2, routeSearchZoom: 2,
maxZoom: 4, maxZoom: 4,
playAudio,
playAudio: false,
needSpotLight, needSpotLight,
scale, scale,
floorHeights: { floorHeights: {
@ -349,7 +304,6 @@ const Index = () => {
dispatchLS({ type: "addLine", data: floorOrder }); dispatchLS({ type: "addLine", data: floorOrder });
}, },
onLoad: (map) => { onLoad: (map) => {
setDisplayMode(1);
setMap(map); setMap(map);
}, },
onAzimuthAngleChange: (angle) => onAzimuthAngleChange: (angle) =>
@ -359,81 +313,32 @@ const Index = () => {
useEffect(() => { useEffect(() => {
if (!mallCode) { if (!mallCode) {
getMallInfo({ memberID }).then((result) => {
getMallInfo().then((result) => {
if (!mallCode) setMallCode(result.mall.code); if (!mallCode) setMallCode(result.mall.code);
setMallInfo(result); setMallInfo(result);
}); });
} }
}, [mallCode]); }, [mallCode]);
const showPopup =
shop !== null &&
!isPick &&
defaultPopupState !== DefaultPopupStates.facList;
const hasCoupon = showPopup && shop && shop.hasCoupon;
const showHeadBar = (start || end) && !inAnimation;
const showHeadBarSearchType = showHeadBar && start && end;
const showNav = inAnimation && start && end; const showNav = inAnimation && start && end;
const showDefaultPopup = !showPopup && !showHeadBar && !showNav && facilities;
const isNavEnd = showHeadBar && start && end;
const exitFromNav = () => { const exitFromNav = () => {
map.setStart(null);
map.setEnd(null); map.setEnd(null);
map.recycle(); map.recycle();
setIsPick(false);
navigation && navigation.stop && navigation.stop(); navigation && navigation.stop && navigation.stop();
dispatchLS({ type: "set", data: null }); dispatchLS({ type: "set", data: null });
setStart(null);
setEnd(null); setEnd(null);
}; };
useEffect(() => {
if (navigation) {
if (openid) {
const isShop = "intro" in end;
const isP = end.isP;
const isDevice = end.isDevice;
}
}
}, [navigation]);
useEffect(() => { useEffect(() => {
if (mallInfo) { if (mallInfo) {
loadMap(); loadMap();
} }
}, [mallInfo]); }, [mallInfo]);
useEffect(() => {
if (map) {
let facs = map.getAllFacilities();
facs = facs
.filter(({ url, typeName }) => url && typeName)
.reduce(
(acc, nxt) =>
acc[nxt.typeName]
? { ...acc, [nxt.typeName]: [...acc[nxt.typeName], nxt] }
: { ...acc, [nxt.typeName]: [nxt] },
{}
);
setFacilities(facs);
}
}, [map]);
return ( return (
<MallCode.Provider value={mallCode}> <MallCode.Provider value={mallCode}>
<div
className={
`index` +
(showDefaultPopup
? defaultPopupState === DefaultPopupStates.init
? " t1"
: defaultPopupState === DefaultPopupStates.moreFac
? " t2"
: " t3"
: "")
}
>
<div className="index">
{!online && ( {!online && (
<Modal <Modal
isOpen={!online} isOpen={!online}
@ -444,77 +349,30 @@ const Index = () => {
<img className="img" src={offline}></img> <img className="img" src={offline}></img>
</Modal> </Modal>
)} )}
<div className={"hud " + (isTyping ? "bg" : "")}>
{mall && (
<div className="hud">
{!(start || end) && ( {!(start || end) && (
<>
<div className="top-left"> <div className="top-left">
<img alt="图左" src={pos} className="left"></img> <img alt="图左" src={pos} className="left"></img>
<span style={{ color: "#7A7E8D" }}>{mall && mall.city}</span> <span style={{ color: "#7A7E8D" }}>{mall && mall.city}</span>
<div className="border"></div> <div className="border"></div>
<span>{mall && mall.name}</span> <span>{mall && mall.name}</span>
</div> </div>
)}
{showHeadBar && (
<HeadBar
mall={mall}
isPick={isPick}
setIsPick={setIsPick}
start={start}
end={end}
floors={mall.floors}
shop={shop}
exit={exitFromNav}
onSwap={swap}
onSetStart={(shop) => {
setStart(shop);
map.startNavigate({ start: shop, end });
}}
onSetEnd={(shop) => {
setEnd(shop);
map.startNavigate({ start, end: shop });
}}
blurMap={() => {
map.blurShop();
map.blurFacility();
}}
searchType={searchType}
onClickSearchType={(id) => {
if (id === searchType) return;
setSearchType(id);
map && map.changeSearchType(id);
}}
showSearchType={start && end}
onIsTypingChange={setIsTyping}
></HeadBar>
<div
className="top-right"
onClick={() => setShowShops(true)}
></div>
</>
)} )}
{((!(start && end) && !isTyping) || showHeadBarSearchType) && (
<More
showHeadBar={showHeadBar}
displayMode={displayMode}
searchType={searchType}
playAudio={playAudio}
setShowOptions={setShowOptions}
onClickDisplayMode={(id) => {
if (id === displayMode) return;
setDisplayMode(id);
map && map.changeDisplayMode(id);
}}
onClickSearchType={(id) => {
if (id === searchType) return;
setSearchType(id);
map && map.changeSearchType(id);
}}
></More>
<div
className={["compass-wrapper", inAnimation ? "inNav" : ""].join(
" "
)} )}
{!isTyping && !showHeadBar && (
<>
>
<img <img
className={[
"compass",
showHeadBar ? "has-header-top" : "",
showNav ? "has-nav-text-top" : "",
start && end ? "has-search-type-top" : "",
].join(" ")}
className="compass"
src={compass} src={compass}
style={{ style={{
transform: `rotate(${ transform: `rotate(${
@ -525,9 +383,9 @@ const Index = () => {
map && !showNav && map.changeFloor(sceneIndex, true) map && !showNav && map.changeFloor(sceneIndex, true)
} }
/> />
</>
)}
</div> </div>
</div>
)}
<div className="qmmap" id={mapId}></div> <div className="qmmap" id={mapId}></div>
<Shops <Shops
@ -541,46 +399,21 @@ const Index = () => {
}} }}
onClose={() => setShowShops(false)} onClose={() => setShowShops(false)}
></Shops> ></Shops>
{mall && !showNav && (
<Popup <Popup
baseUrl={mall && mall.baseUrl}
showPopup={showPopup}
defaultPopup={
showDefaultPopup && (
<DefaultPopup
state={defaultPopupState}
setState={setDefaultPopupState}
facilities={facilities}
onSearch={() => {
setShowShops(true);
}}
onClickFac={(id) => {
setDoFocus(2);
map && map.focusFacilityById(id);
}}
setEnd={(fac) => {
setEnd(fac);
setShop(null);
}}
blurMap={() => {
setShop(null);
map.blurShop();
map.blurFacility();
}}
shop={shop}
sceneIndex={sceneIndex}
mall={mall} mall={mall}
onClick={({ houseNum }) => { onClick={({ houseNum }) => {
setShowShops(false); setShowShops(false);
setDoFocus(2); setDoFocus(2);
map.focusShopByHouseNum(houseNum); map.focusShopByHouseNum(houseNum);
}} }}
></DefaultPopup>
)
}
floors={ floors={
mall && mall &&
sceneIndex !== null &&
(defaultPopupState !== DefaultPopupStates.moreFac ||
!showDefaultPopup) && (
sceneIndex !== null && (
<Floors <Floors
start={start}
end={end} end={end}
clickable={map && !showNav} clickable={map && !showNav}
showNav={showNav} showNav={showNav}
@ -588,29 +421,19 @@ const Index = () => {
floors={mall.floors} floors={mall.floors}
sceneIndex={sceneIndex} sceneIndex={sceneIndex}
setSceneIndex={setSceneIndex} setSceneIndex={setSceneIndex}
isNavEnd={isNavEnd}
mall={mall} mall={mall}
hasCoupon={hasCoupon}
></Floors> ></Floors>
) )
} }
shop={shop}
closePopup={() => {
setShop(null);
history.replace(`/?openid=${openid}`);
map.blurShop();
map.blurFacility();
}}
showDetail={() => setShop({ ...shop, showDetail: true })}
setEnd={() => {
setEnd(shop);
setShop(null);
}}
handleAR={(shop) => {
setARShop(shop);
setShowARPrompt(true);
onClickActive={(end) => {
setEnd(end);
map.startNavigate({
start,
end,
});
}} }}
></Popup> ></Popup>
)}
{showNav && ( {showNav && (
<NavBottom <NavBottom
baseUrl={mall && mall.baseUrl} baseUrl={mall && mall.baseUrl}
@ -635,22 +458,8 @@ const Index = () => {
routeSearchText={routeSearchText} routeSearchText={routeSearchText}
percent={percent} percent={percent}
elevations={elevations} elevations={elevations}
handleAR={(shop) => {
setARShop(shop);
setShowARPrompt(true);
}}
></NavBottom> ></NavBottom>
)} )}
{isNavEnd && (
<div
className="nav-button"
onClick={() => {
map.startNavigate({ start, end });
}}
>
开始导航
</div>
)}
</div> </div>
</MallCode.Provider> </MallCode.Provider>
); );

107
src/pages/Index/Index.scss

@ -158,23 +158,13 @@ body {
position: fixed; position: fixed;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: #dee6f6;
&.hasTab { &.hasTab {
height: calc(100vh - 84px); height: calc(100vh - 84px);
} }
overscroll-behavior: none; overscroll-behavior: none;
&.t1,
&.t2 {
.qmmap {
margin-top: -88px;
}
}
&.t3 {
.qmmap {
margin-top: -160px;
}
}
.hud { .hud {
position: fixed; position: fixed;
z-index: 3000; z-index: 3000;
@ -186,18 +176,29 @@ body {
&.bg { &.bg {
background: #f0f0f0; background: #f0f0f0;
} }
.compass {
.compass-wrapper {
position: absolute; position: absolute;
top: 52px;
left: 10px;
width: 34px;
height: 34px;
transform-origin: center;
bottom: 326px;
right: 14px;
width: 40px;
height: 40px;
display: flex;
pointer-events: auto; pointer-events: auto;
&.has-nav-text-top {
top: 50px;
background: #ffffff;
box-shadow: 0px 8px 8px rgba(104, 110, 127, 0.04);
border-radius: 8px;
justify-content: center;
align-items: center;
&.inNav {
bottom: 256px;
} }
.compass {
width: 32px;
height: 32px;
transform-origin: center;
} }
}
.car { .car {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -218,13 +219,11 @@ body {
} }
.top-left { .top-left {
position: absolute; position: absolute;
top: 10px;
left: 10px;
top: 8px;
left: 14px;
display: inline-flex; display: inline-flex;
border-radius: 20px; border-radius: 20px;
background: #fff; background: #fff;
font-family: PingFang SC;
font-style: normal;
font-weight: 500; font-weight: 500;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
@ -242,47 +241,54 @@ body {
.border { .border {
width: 1px; width: 1px;
height: 10px; height: 10px;
background: #c9cbd1;
background: rgba(0, 0, 0, 0.2);
margin: 0 8px; margin: 0 8px;
} }
} }
.top-right { .top-right {
position: absolute; position: absolute;
top: 12px;
width: 168px;
height: 50px;
top: 8px;
right: 14px; right: 14px;
border-radius: 15px;
color: #a9a9a9;
background: #fff;
line-height: 30px;
padding: 0 12px 0 35px;
font-size: 11px;
z-index: 1;
}
.top-right img {
position: absolute;
top: 9px;
left: 13px;
width: 13px;
border-radius: 12px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.03);
background: center / cover no-repeat url(./topRight.png);
pointer-events: auto;
} }
} }
.qmmap-container { .qmmap-container {
.wrapper { .wrapper {
.focus-text { .focus-text {
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
padding: 0 12px;
border: 1px solid #437af7;
border-radius: 20px;
height: 25px;
display: flex;
align-items: baseline;
background: #516dd8;
border: none;
padding: 0 14px;
border-radius: 100px;
height: 30px;
line-height: 30px;
font-weight: 700;
font-size: 12px;
&::after {
display: inline-block;
content: "GO";
font-size: 15px;
height: 12px;
line-height: 12px;
border-left: 1px solid rgba(255, 255, 255, 0.2);
margin-left: 9px;
padding-left: 7px;
}
.down-arrow-wrapper { .down-arrow-wrapper {
width: 6px;
height: 6px;
background-image: url(./arrow.png);
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 10px;
height: 10px;
background: #516dd8;
transform-origin: center;
transform: rotate(45deg);
border: none; border: none;
bottom: -6px;
bottom: -3px;
overflow: visible; overflow: visible;
.down-arrow { .down-arrow {
display: none; display: none;
@ -307,6 +313,7 @@ body {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
margin-top: -120px;
overscroll-behavior: none; overscroll-behavior: none;
overflow: hidden; overflow: hidden;
transition: margin-top 0.5s ease; transition: margin-top 0.5s ease;

BIN
src/pages/Index/ar.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

BIN
src/pages/Index/more.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

15
src/pages/Index/tabs/Tabs.js

@ -1,15 +0,0 @@
import act from "./act.svg";
import actActive from "./actActive.svg";
import car from "./car.svg";
import carActive from "./carActive.svg";
import map from "./map.svg";
import mapActive from "./mapActive.svg";
import my from "./my.svg";
import myActive from "./myActive.svg";
const TabMap = {
活动: { logo: act, logoActive: actActive },
寻车: { logo: car, logoActive: carActive },
地图: { logo: map, logoActive: mapActive },
我的: { logo: my, logoActive: myActive },
};
export default TabMap;

3
src/pages/Index/tabs/act.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.72554 4.12963C6.72554 3.42759 6.90231 3.05169 7.10939 2.84641C7.31497 2.64263 7.68944 2.46929 8.39221 2.46929H11.7255C12.4283 2.46929 12.8028 2.64263 13.0084 2.84641C13.2155 3.05169 13.3922 3.42759 13.3922 4.12963V9.89581C13.3922 10.5366 13.1683 10.7517 13.0578 10.8111C12.9403 10.8742 12.6168 10.9426 12.0395 10.6023L12.0382 10.6016L10.9408 9.94881L10.9376 9.94694C10.655 9.78052 10.3359 9.71996 10.0589 9.71996C9.78185 9.71996 9.46272 9.78051 9.18013 9.94693L8.07953 10.6016L8.0783 10.6023C7.50098 10.9426 7.1775 10.8742 7.05998 10.8111C6.94942 10.7517 6.72554 10.5366 6.72554 9.89581V4.12963ZM8.39221 0.833496C7.42832 0.833496 6.55279 1.0732 5.92503 1.6955C5.47928 2.13737 5.22926 2.70207 5.12217 3.3335H5.05888C2.75769 3.3335 0.892212 5.19898 0.892212 7.50016V15.0002C0.892212 17.3013 2.75769 19.1668 5.05888 19.1668H15.0589C17.3601 19.1668 19.2255 17.3013 19.2255 15.0002V7.50016C19.2255 5.19898 17.3601 3.3335 15.0589 3.3335H14.9956C14.8885 2.70207 14.6385 2.13737 14.1927 1.6955C13.565 1.0732 12.6894 0.833496 11.7255 0.833496H8.39221ZM15.0589 5.00016L15.0589 9.89581C15.0589 10.8826 14.6953 11.7963 13.8579 12.246C13.0276 12.692 12.0431 12.5131 11.1795 12.0036L11.177 12.0021L10.096 11.3591C10.0877 11.3574 10.0748 11.3558 10.0589 11.3558C10.043 11.3558 10.0301 11.3574 10.0217 11.3591L8.9408 12.0021L8.93823 12.0036C8.07465 12.5131 7.09017 12.692 6.25986 12.246C5.4225 11.7963 5.05888 10.8826 5.05888 9.89581L5.05888 5.00016C3.67817 5.00016 2.55888 6.11945 2.55888 7.50016V15.0002C2.55888 16.3809 3.67817 17.5002 5.05888 17.5002H15.0589C16.4396 17.5002 17.5589 16.3809 17.5589 15.0002V7.50016C17.5589 6.11945 16.4396 5.00016 15.0589 5.00016Z" fill="#A1A5B3"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

3
src/pages/Index/tabs/actActive.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.72554 4.12963C6.72554 3.42759 6.90231 3.05169 7.10939 2.84641C7.31497 2.64263 7.68944 2.46929 8.39221 2.46929H11.7255C12.4283 2.46929 12.8028 2.64263 13.0084 2.84641C13.2155 3.05169 13.3922 3.42759 13.3922 4.12963V9.89581C13.3922 10.5366 13.1683 10.7517 13.0578 10.8111C12.9403 10.8742 12.6168 10.9426 12.0395 10.6023L12.0382 10.6016L10.9408 9.94881L10.9376 9.94694C10.655 9.78052 10.3359 9.71996 10.0589 9.71996C9.78185 9.71996 9.46272 9.78051 9.18013 9.94693L8.07953 10.6016L8.0783 10.6023C7.50098 10.9426 7.1775 10.8742 7.05998 10.8111C6.94942 10.7517 6.72554 10.5366 6.72554 9.89581V4.12963ZM8.39221 0.833496C7.42832 0.833496 6.55279 1.0732 5.92503 1.6955C5.47928 2.13737 5.22926 2.70207 5.12217 3.3335H5.05888C2.75769 3.3335 0.892212 5.19898 0.892212 7.50016V15.0002C0.892212 17.3013 2.75769 19.1668 5.05888 19.1668H15.0589C17.3601 19.1668 19.2255 17.3013 19.2255 15.0002V7.50016C19.2255 5.19898 17.3601 3.3335 15.0589 3.3335H14.9956C14.8885 2.70207 14.6385 2.13737 14.1927 1.6955C13.565 1.0732 12.6894 0.833496 11.7255 0.833496H8.39221ZM15.0589 5.00016L15.0589 9.89581C15.0589 10.8826 14.6953 11.7963 13.8579 12.246C13.0276 12.692 12.0431 12.5131 11.1795 12.0036L11.177 12.0021L10.096 11.3591C10.0877 11.3574 10.0748 11.3558 10.0589 11.3558C10.043 11.3558 10.0301 11.3574 10.0217 11.3591L8.9408 12.0021L8.93823 12.0036C8.07465 12.5131 7.09017 12.692 6.25986 12.246C5.4225 11.7963 5.05888 10.8826 5.05888 9.89581L5.05888 5.00016C3.67817 5.00016 2.55888 6.11945 2.55888 7.50016V15.0002C2.55888 16.3809 3.67817 17.5002 5.05888 17.5002H15.0589C16.4396 17.5002 17.5589 16.3809 17.5589 15.0002V7.50016C17.5589 6.11945 16.4396 5.00016 15.0589 5.00016Z" fill="#437AF7"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

10
src/pages/Index/tabs/car.svg

@ -1,10 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1152_4008)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.61438 5.31121C4.50605 3.10827 6.64501 1.6665 9.02157 1.6665H14.647C15.6655 1.6665 16.5822 2.2844 16.9643 3.22852L18.6058 7.28383C19.1298 7.74209 19.4609 8.41564 19.4609 9.1665V14.1665C19.4609 15.087 18.7147 15.8332 17.7942 15.8332H17.6892C17.3191 17.2709 16.0141 18.3332 14.4609 18.3332C12.9077 18.3332 11.6026 17.2709 11.2325 15.8332H9.35584C8.98581 17.2709 7.68072 18.3332 6.12752 18.3332C4.57432 18.3332 3.26924 17.2709 2.8992 15.8332H1.96086C1.04038 15.8332 0.294189 15.087 0.294189 14.1665V10.8332C0.294189 9.06421 1.39655 7.55271 2.9518 6.94818L3.61438 5.31121ZM17.7942 14.1665H17.6892C17.3191 12.7288 16.0141 11.6665 14.4609 11.6665C12.9077 11.6665 11.6026 12.7288 11.2325 14.1665H9.35584C8.98581 12.7288 7.68072 11.6665 6.12752 11.6665C4.57432 11.6665 3.26924 12.7288 2.8992 14.1665H1.96086V10.8332C1.96086 9.45246 3.08014 8.33317 4.46086 8.33317H16.9609C17.4211 8.33317 17.7942 8.70627 17.7942 9.1665V14.1665ZM12.7942 6.6665H16.5579L15.4194 3.85384C15.292 3.53914 14.9865 3.33317 14.647 3.33317H12.7942V6.6665ZM11.1275 6.6665V3.33317H9.02157C7.32402 3.33317 5.7962 4.363 5.15929 5.93653L4.86383 6.6665H11.1275ZM6.12752 13.3332C5.20705 13.3332 4.46086 14.0794 4.46086 14.9998C4.46086 15.9203 5.20705 16.6665 6.12752 16.6665C7.048 16.6665 7.79419 15.9203 7.79419 14.9998C7.79419 14.0794 7.048 13.3332 6.12752 13.3332ZM14.4609 13.3332C13.5404 13.3332 12.7942 14.0794 12.7942 14.9998C12.7942 15.9203 13.5404 16.6665 14.4609 16.6665C15.3813 16.6665 16.1275 15.9203 16.1275 14.9998C16.1275 14.0794 15.3813 13.3332 14.4609 13.3332Z" fill="#A1A5B3"/>
</g>
<defs>
<clipPath id="clip0_1152_4008">
<rect width="20" height="20" fill="white" transform="translate(0.294189)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

10
src/pages/Index/tabs/carActive.svg

@ -1,10 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1152_4131)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.61438 5.3117C4.50605 3.10875 6.64501 1.66699 9.02157 1.66699H14.647C15.6655 1.66699 16.5822 2.28489 16.9643 3.22901L18.6058 7.28432C19.1298 7.74258 19.4609 8.41613 19.4609 9.16699V14.167C19.4609 15.0875 18.7147 15.8337 17.7942 15.8337H17.6892C17.3191 17.2713 16.0141 18.3337 14.4609 18.3337C12.9077 18.3337 11.6026 17.2713 11.2325 15.8337H9.35584C8.98581 17.2713 7.68072 18.3337 6.12752 18.3337C4.57432 18.3337 3.26924 17.2713 2.8992 15.8337H1.96086C1.04038 15.8337 0.294189 15.0875 0.294189 14.167V10.8337C0.294189 9.06469 1.39655 7.5532 2.9518 6.94866L3.61438 5.3117ZM17.7942 14.167H17.6892C17.3191 12.7293 16.0141 11.667 14.4609 11.667C12.9077 11.667 11.6026 12.7293 11.2325 14.167H9.35584C8.98581 12.7293 7.68072 11.667 6.12752 11.667C4.57432 11.667 3.26924 12.7293 2.8992 14.167H1.96086V10.8337C1.96086 9.45295 3.08014 8.33366 4.46086 8.33366H16.9609C17.4211 8.33366 17.7942 8.70675 17.7942 9.16699V14.167ZM12.7942 6.66699H16.5579L15.4194 3.85433C15.292 3.53963 14.9865 3.33366 14.647 3.33366H12.7942V6.66699ZM11.1275 6.66699V3.33366H9.02157C7.32402 3.33366 5.7962 4.36349 5.15929 5.93702L4.86383 6.66699H11.1275ZM6.12752 13.3337C5.20705 13.3337 4.46086 14.0799 4.46086 15.0003C4.46086 15.9208 5.20705 16.667 6.12752 16.667C7.048 16.667 7.79419 15.9208 7.79419 15.0003C7.79419 14.0799 7.048 13.3337 6.12752 13.3337ZM14.4609 13.3337C13.5404 13.3337 12.7942 14.0799 12.7942 15.0003C12.7942 15.9208 13.5404 16.667 14.4609 16.667C15.3813 16.667 16.1275 15.9208 16.1275 15.0003C16.1275 14.0799 15.3813 13.3337 14.4609 13.3337Z" fill="#437AF7"/>
</g>
<defs>
<clipPath id="clip0_1152_4131">
<rect width="20" height="20" fill="white" transform="translate(0.294189)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

3
src/pages/Index/tabs/map.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.3431 2.49967H6.00977C4.16882 2.49967 2.67643 3.99206 2.67643 5.83301V14.1663C2.67643 15.6515 3.64767 16.9097 4.98962 17.3407L16.9396 3.74248C16.3285 2.98455 15.3924 2.49967 14.3431 2.49967ZM14.3431 17.4997H7.06867L11.4936 12.4644L16.4719 16.7315C15.8945 17.2112 15.1525 17.4997 14.3431 17.4997ZM17.6764 14.1663C17.6764 14.5927 17.5964 15.0004 17.4505 15.3751L12.5939 11.2123L17.655 5.45314C17.6692 5.5778 17.6764 5.70456 17.6764 5.83301V14.1663ZM6.00977 0.833008C3.24834 0.833008 1.00977 3.07158 1.00977 5.83301V14.1663C1.00977 16.9278 3.24834 19.1663 6.00976 19.1663H14.3431C17.1045 19.1663 19.3431 16.9278 19.3431 14.1663V5.83301C19.3431 3.07158 17.1045 0.833008 14.3431 0.833008H6.00977ZM10.859 5.76291C10.4706 4.08902 9.01011 3.28672 7.64728 3.28672C6.28455 3.28672 4.82413 4.08927 4.43552 5.76291C3.99446 7.66035 5.21025 9.1694 6.04083 9.95627L6.04228 9.95763C6.94379 10.8076 8.35554 10.8139 9.25509 9.95498C10.0896 9.16399 11.2889 7.65844 10.86 5.76703L10.859 5.76291ZM7.64728 4.95339C6.89344 4.95339 6.23722 5.37193 6.05903 6.1397C5.83376 7.10839 6.43393 8.03257 7.18622 8.74553C7.48633 9.02786 7.89929 8.95041 8.17159 8.6847C8.88946 7.98421 9.44832 7.08315 9.23505 6.13765C9.05617 5.37118 8.40045 4.95339 7.64728 4.95339ZM8.50977 6.66634C8.50977 7.12658 8.13667 7.49967 7.67643 7.49967C7.21619 7.49967 6.8431 7.12658 6.8431 6.66634C6.8431 6.2061 7.21619 5.83301 7.67643 5.83301C8.13667 5.83301 8.50977 6.2061 8.50977 6.66634Z" fill="#A1A5B3"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

3
src/pages/Index/tabs/mapActive.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.3432 2.50016H6.00989C4.16894 2.50016 2.67655 3.99255 2.67655 5.8335V14.1668C2.67655 15.652 3.64779 16.9102 4.98974 17.3412L16.9397 3.74297C16.3287 2.98504 15.3926 2.50016 14.3432 2.50016ZM14.3432 17.5002H7.06879L11.4938 12.4649L16.472 16.7319C15.8946 17.2117 15.1526 17.5002 14.3432 17.5002ZM17.6766 14.1668C17.6766 14.5932 17.5965 15.0009 17.4506 15.3756L12.594 11.2128L17.6551 5.45362C17.6693 5.57829 17.6766 5.70505 17.6766 5.8335V14.1668ZM6.00989 0.833496C3.24846 0.833496 1.00989 3.07207 1.00989 5.8335V14.1668C1.00989 16.9283 3.24846 19.1668 6.00989 19.1668H14.3432C17.1046 19.1668 19.3432 16.9283 19.3432 14.1668V5.8335C19.3432 3.07207 17.1046 0.833496 14.3432 0.833496H6.00989ZM10.8592 5.7634C10.4707 4.08951 9.01023 3.28721 7.6474 3.28721C6.28468 3.28721 4.82425 4.08976 4.43564 5.7634C3.99458 7.66084 5.21037 9.16989 6.04096 9.95676L6.0424 9.95812C6.94391 10.8081 8.35566 10.8144 9.25521 9.95547C10.0897 9.16448 11.289 7.65893 10.8601 5.76752L10.8592 5.7634ZM7.6474 4.95388C6.89356 4.95388 6.23734 5.37242 6.05916 6.14019C5.83388 7.10888 6.43405 8.03305 7.18634 8.74602C7.48646 9.02834 7.89941 8.9509 8.17171 8.68519C8.88958 7.98469 9.44844 7.08363 9.23517 6.13814C9.05629 5.37167 8.40058 4.95388 7.6474 4.95388ZM8.50989 6.66683C8.50989 7.12707 8.13679 7.50016 7.67655 7.50016C7.21632 7.50016 6.84322 7.12707 6.84322 6.66683C6.84322 6.20659 7.21632 5.8335 7.67655 5.8335C8.13679 5.8335 8.50989 6.20659 8.50989 6.66683Z" fill="#437AF7"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

3
src/pages/Index/tabs/my.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.24516 6.66683C6.24516 4.36564 8.11064 2.50016 10.4118 2.50016C12.713 2.50016 14.5785 4.36564 14.5785 6.66683C14.5785 8.96802 12.713 10.8335 10.4118 10.8335C8.11064 10.8335 6.24516 8.96802 6.24516 6.66683ZM10.4118 0.833496C7.19016 0.833496 4.57849 3.44517 4.57849 6.66683C4.57849 8.65136 5.56949 10.4044 7.08362 11.4582C4.17219 12.601 2.07849 15.2016 2.07849 18.3335C2.07849 18.7937 2.45159 19.1668 2.91182 19.1668C3.37206 19.1668 3.74516 18.7937 3.74516 18.3335C3.74516 15.1981 6.63794 12.5002 10.4118 12.5002C14.1857 12.5002 17.0785 15.1981 17.0785 18.3335C17.0785 18.7937 17.4516 19.1668 17.9118 19.1668C18.3721 19.1668 18.7452 18.7937 18.7452 18.3335C18.7452 15.2016 16.6515 12.601 13.74 11.4582C15.2542 10.4044 16.2452 8.65136 16.2452 6.66683C16.2452 3.44517 13.6335 0.833496 10.4118 0.833496Z" fill="#A1A5B3"/>
</svg>

Before

Width:  |  Height:  |  Size: 971 B

3
src/pages/Index/tabs/myActive.svg

@ -1,3 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.24528 6.66634C6.24528 4.36515 8.11076 2.49967 10.4119 2.49967C12.7131 2.49967 14.5786 4.36515 14.5786 6.66634C14.5786 8.96674 12.7144 10.8317 10.4143 10.833C10.4135 10.833 10.4127 10.833 10.4119 10.833C8.11076 10.833 6.24528 8.96753 6.24528 6.66634ZM7.08374 11.4577C5.56961 10.4039 4.57861 8.65087 4.57861 6.66634C4.57861 3.44468 7.19029 0.833008 10.4119 0.833008C13.6336 0.833008 16.2453 3.44468 16.2453 6.66634C16.2453 8.65087 15.2543 10.4039 13.7401 11.4577C16.6516 12.6006 18.7453 15.2011 18.7453 18.333C18.7453 18.7932 18.3722 19.1663 17.9119 19.1663C17.4517 19.1663 17.0786 18.7932 17.0786 18.333C17.0786 15.1976 14.1858 12.4997 10.4119 12.4997C6.63807 12.4997 3.74528 15.1976 3.74528 18.333C3.74528 18.7932 3.37218 19.1663 2.91195 19.1663C2.45171 19.1663 2.07861 18.7932 2.07861 18.333C2.07861 15.2011 4.17231 12.6006 7.08374 11.4577Z" fill="#437AF7"/>
</svg>

Before

Width:  |  Height:  |  Size: 1015 B

BIN
src/pages/Index/topRight.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

104
src/pages/Keyboard/Keyboard.js

@ -1,104 +0,0 @@
import React from "react";
import "./Keyboard.scss";
const N1 = "1234567890";
const N2 = "QWERTYUIOP";
const N3 = "ASDFGHJKL";
const N4 = "ZXCVBNM";
const C1 = "京津渝沪冀晋辽吉黑苏";
const C2 = "浙皖闽赣鲁豫鄂湘粤琼";
const C3 = "川贵云陕甘青蒙桂宁新";
const C4 = "藏使领警学港澳";
const Keyboard = ({
isNum,
onInput,
onBackspace,
onSetIsNum,
onClose,
onFinish,
}) => {
return (
<div className="keyboard">
<div className="bar">
<div className="btn1" onClick={onClose}>
取消
</div>
<div className="btn2" onClick={onFinish}>
完成
</div>
</div>
{isNum ? (
<div className="plane">
<div className="row">
{N1.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
{N2.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
{N3.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
<div className="key1" onClick={() => onSetIsNum(false)}>
</div>
{N4.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
<div className="key2" onClick={onBackspace}></div>
</div>
</div>
) : (
<div className="plane">
<div className="row">
{C1.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
{C2.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
{C3.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
</div>
<div className="row">
<div className="key1" onClick={() => onSetIsNum(true)}>
ABC
</div>
{C4.split("").map((key) => (
<div className="key" key={key} onClick={() => onInput(key)}>
{key}
</div>
))}
<div className="key2" onClick={onBackspace}></div>
</div>
</div>
)}
<div className="safe"></div>
</div>
);
};
export default Keyboard;

128
src/pages/Keyboard/Keyboard.scss

@ -1,128 +0,0 @@
.keyboard {
position: absolute;
bottom: -98px;
left: 0;
right: 0;
display: flex;
flex-direction: column;
width: 100vw;
height: 294px;
z-index: 10;
.bar {
display: flex;
flex: 0 0 40px;
justify-content: space-between;
line-height: 40px;
background: #ffffff;
box-shadow: 0px -1px 12px rgba(0, 0, 0, 0.05);
.btn1 {
position: relative;
flex: 0 0 80px;
text-align: center;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: normal;
font-size: 16px;
color: #4f4f4f;
&::after {
content: "";
position: absolute;
top: 14px;
right: 0;
width: 1px;
height: 14px;
background: #e0e0e0;
}
}
.btn2 {
position: relative;
flex: 0 0 80px;
text-align: center;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: bold;
font-size: 16px;
color: #437af7;
&::after {
content: "";
position: absolute;
top: 14px;
left: 0;
width: 1px;
height: 14px;
background: #e0e0e0;
}
}
}
.safe {
flex: 0 0 34px;
background: #d1d5db;
}
.plane {
flex: 1;
background: #d1d5db;
.row {
display: flex;
width: 100vw;
justify-content: center;
padding-top: 12px;
}
.key {
width: 8.5333vw;
height: 40px;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 40px;
text-align: center;
color: #333333;
background: #ffffff;
box-shadow: 0px 1px 0px #898a8d;
border-radius: 4px;
&.bold {
font-weight: bold;
}
&:active {
background: #0166b3;
box-shadow: 0px 2px 1px rgba(0, 0, 0, 0.2);
color: #ffffff;
}
}
.key + .key {
margin-left: 1.0667vw;
}
.key1 {
width: 13.3333vw;
height: 40px;
background: linear-gradient(180deg, #508af7 0%, #5ea5f9 100%);
color: #fff;
box-shadow: 0px 2px 1px rgba(0, 0, 0, 0.2);
border-radius: 4px;
font-family: Noto IKEA Simplified Chinese;
font-style: normal;
font-weight: normal;
font-size: 16px;
line-height: 40px;
text-align: center;
}
.key1 + .key {
margin-left: 1.0667vw;
}
.key2 {
width: 13.3333vw;
height: 40px;
background: #adb3bc;
color: #fff;
box-shadow: 0px 2px 1px rgba(0, 0, 0, 0.2);
border-radius: 4px;
background-image: url(./backspace.png);
background-repeat: no-repeat;
background-size: 20px;
background-position: center;
}
.key + .key2 {
margin-left: 1.0667vw;
}
}
}

BIN
src/pages/Keyboard/backspace.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

19
src/pages/Shops/Shops.js

@ -5,17 +5,13 @@ import ShopList from "../../components/ShopList/ShopList.js";
import search from "./search.png"; import search from "./search.png";
import close from "./close.png"; import close from "./close.png";
import back from "./back.png"; import back from "./back.png";
import ShopsWithFilter from "../../components/ShopsWithFilter/ShopsWithFilter";
const Shops = ({ mall, isOpen, onRequestClose, onClick, onClose }) => { const Shops = ({ mall, isOpen, onRequestClose, onClick, onClose }) => {
const [q, setQ] = useState(""); const [q, setQ] = useState("");
const [resetShopsWithFilter, setResetShopsWithFilter] = useState(false);
useEffect(() => {
setResetShopsWithFilter(true);
}, [q]);
return ( return (
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
style={{ overlay: { zIndex: 10000, background: "#fff" } }}
style={{ overlay: { zIndex: 10000, background: "#DEE6F6" } }}
ariaHideApp={false} ariaHideApp={false}
className="shops" className="shops"
onRequestClose={() => onRequestClose()} onRequestClose={() => onRequestClose()}
@ -26,7 +22,6 @@ const Shops = ({ mall, isOpen, onRequestClose, onClick, onClose }) => {
value={q} value={q}
className="input" className="input"
onChange={(e) => setQ(e.target.value)} onChange={(e) => setQ(e.target.value)}
placeholder="查找店铺"
/> />
<img alt="搜索图标" className="search" src={search} /> <img alt="搜索图标" className="search" src={search} />
{q && ( {q && (
@ -40,16 +35,6 @@ const Shops = ({ mall, isOpen, onRequestClose, onClick, onClose }) => {
></img> ></img>
)} )}
</div> </div>
{!q && (
<ShopsWithFilter
mall={mall}
onClick={onClick}
reset={resetShopsWithFilter}
onReset={() => setResetShopsWithFilter(false)}
wingHeight="calc(100vh - 157px)"
></ShopsWithFilter>
)}
{q && ( {q && (
<div className="search-list"> <div className="search-list">
<ShopList mall={mall} isRow={true} q={q} onClick={onClick}></ShopList> <ShopList mall={mall} isRow={true} q={q} onClick={onClick}></ShopList>

62
src/pages/Shops/Shops.scss

@ -1,7 +1,7 @@
.shops { .shops {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: #f5f5f5;
background: #dee6f6;
position: relative; position: relative;
font-family: SourceHanSansCN-Regular, SourceHanSansCN; font-family: SourceHanSansCN-Regular, SourceHanSansCN;
outline: none; outline: none;
@ -9,27 +9,24 @@
position: relative; position: relative;
display: flex; display: flex;
width: 100vw; width: 100vw;
padding: 16px 10px 0 10px;
padding: 8px 14px 0 14px;
align-items: center; align-items: center;
.back { .back {
flex: 0 0 60px;
height: 60px;
flex: 0 0 72px;
height: 72px;
} }
.input { .input {
flex: 1; flex: 1;
width: calc(100vw - 20px - 60px - 14px);
width: calc(100vw - 114px);
margin-left: 14px; margin-left: 14px;
background: #fff; background: #fff;
padding: 0 48px 0 60px;
font-family: PingFang SC;
font-style: normal;
padding: 0 72px 0 64px;
font-weight: 600; font-weight: 600;
font-size: 16px;
line-height: 22px;
color: #323337;
border-radius: 10px;
font-size: 20px;
color: rgba(0, 0, 0, 0.8);
border-radius: 12px;
box-sizing: border-box; box-sizing: border-box;
height: 60px;
height: 72px;
border: none; border: none;
outline: none; outline: none;
&::placeholder { &::placeholder {
@ -43,45 +40,22 @@
.search { .search {
position: absolute; position: absolute;
top: 30px; top: 30px;
left: 98px;
width: 32px;
height: 32px;
left: 116px;
width: 28px;
height: 28px;
pointer-events: none; pointer-events: none;
} }
.close { .close {
position: absolute; position: absolute;
width: 36px;
height: 36px;
top: 28px;
right: 22px;
}
}
.wings {
display: flex;
width: 100vw;
height: calc(100vh - 156px);
border-top: 1px solid #edeff3;
margin-top: 8px;
.left {
width: 96px;
flex: 0 0 96px;
height: calc(100vh - 157px);
background: #edeff3;
overflow-x: hidden;
overflow-y: auto;
}
.right {
flex: 1;
height: calc(100vh - 157px);
background: #f3f4f8;
overflow-x: hidden;
overflow-y: auto;
width: 38px;
height: 38px;
top: 25px;
right: 31px;
} }
} }
.search-list { .search-list {
width: 100vw; width: 100vw;
height: calc(100vh - 98px);
margin-top: 6px;
height: calc(100vh - 80px);
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
} }

BIN
src/pages/Shops/back.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/pages/Shops/close.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save