chenlei 1 年之前
父節點
當前提交
e00185badf
共有 45 個文件被更改,包括 453 次插入255 次删除
  1. 12 0
      src/api/index.ts
  2. 4 0
      src/app.scss
  3. 4 2
      src/app.tsx
  4. 二進制
      src/components/PageSwiper/images/bg@2x-min.jpg
  5. 二進制
      src/components/PageSwiper/images/box1@2x-min.png
  6. 二進制
      src/components/PageSwiper/images/pic-or-2@2x-min.jpg
  7. 二進制
      src/components/PageSwiper/images/pic-or-3@2x-min.jpg
  8. 二進制
      src/components/PageSwiper/images/pic-or@2x-min.jpg
  9. 9 0
      src/components/PageSwiper/index.scss
  10. 7 0
      src/components/PageSwiper/index.tsx
  11. 二進制
      src/images/line-sights/16.png
  12. 二進制
      src/images/line-sights/17.png
  13. 二進制
      src/images/line-sights/18.png
  14. 二進制
      src/images/line-sights/19.png
  15. 二進制
      src/images/sights/16.png
  16. 二進制
      src/images/sights/17.png
  17. 二進制
      src/images/sights/18.png
  18. 二進制
      src/images/sights/19.png
  19. 二進制
      src/images/source-sights/16.jpg
  20. 二進制
      src/images/source-sights/17.jpg
  21. 二進制
      src/images/source-sights/18.jpg
  22. 二進制
      src/images/source-sights/19.jpg
  23. 34 15
      src/pages/home/components/Menu/index.tsx
  24. 9 2
      src/pages/home/components/RoundItem/index.tsx
  25. 7 0
      src/pages/home/components/SearchLayout/index.scss
  26. 2 1
      src/pages/home/components/SearchLayout/index.tsx
  27. 15 5
      src/pages/home/components/SightDetailLayout/index.scss
  28. 56 51
      src/pages/home/components/SightDetailLayout/index.tsx
  29. 14 16
      src/pages/home/components/Swiper/index.tsx
  30. 31 38
      src/pages/home/components/VisitCard/index.tsx
  31. 9 5
      src/pages/home/constants.ts
  32. 3 1
      src/pages/home/index.config.ts
  33. 23 10
      src/pages/home/index.scss
  34. 60 49
      src/pages/home/index.tsx
  35. 4 4
      src/pages/login/index.tsx
  36. 5 2
      src/store/base.ts
  37. 2 0
      src/subModule/pages/feedback/index.tsx
  38. 5 3
      src/subModule/pages/order/index.tsx
  39. 4 0
      src/subModule/pages/shopmall/components/Products/index.scss
  40. 38 32
      src/subModule/pages/shopmall/components/Products/index.tsx
  41. 12 0
      src/subModule/pages/shopmall/components/Records/index.scss
  42. 36 17
      src/subModule/pages/shopmall/components/Records/index.tsx
  43. 15 0
      src/subModule/pages/shopmall/index.scss
  44. 33 2
      src/utils/index.ts
  45. 二進制
      src/videos/city.mp4

+ 12 - 0
src/api/index.ts

@@ -80,3 +80,15 @@ export const validateNickName = (name: string) => {
     },
   });
 };
+
+export const getShopRuleApi = () => {
+  return requestByPost("/api/show/getRuleConfig", undefined, {
+    meta: {
+      showLoading: true,
+    },
+  });
+};
+
+export const handleVisitStateApi = (m: number) => {
+  return requestByGet(`/api/cms/game/user/update/invite/${m}`);
+};

+ 4 - 0
src/app.scss

@@ -7,6 +7,10 @@ page,
   margin-bottom: constant(safe-area-inset-bottom);
   margin-bottom: env(safe-area-inset-bottom);
 }
+.padding-safe-area-bottom {
+  padding-bottom: constant(safe-area-inset-bottom) !important;
+  padding-bottom: env(safe-area-inset-bottom) !important;
+}
 
 .limit-line {
   overflow: hidden;

+ 4 - 2
src/app.tsx

@@ -4,7 +4,7 @@ import { Provider } from "mobx-react";
 import { compose, initial } from "@dage/service";
 
 import store from "./store";
-import { TOKEN_KEY } from "./utils";
+import { login, TOKEN_KEY } from "./utils";
 import { $fetch } from "./utils/fetch";
 
 import "./app.scss";
@@ -68,7 +68,9 @@ initial({
 });
 
 class App extends Component {
-  componentDidMount() {}
+  componentDidMount() {
+    login();
+  }
 
   componentDidShow() {}
 

二進制
src/components/PageSwiper/images/bg@2x-min.jpg


二進制
src/components/PageSwiper/images/box1@2x-min.png


二進制
src/components/PageSwiper/images/pic-or-2@2x-min.jpg


二進制
src/components/PageSwiper/images/pic-or-3@2x-min.jpg


二進制
src/components/PageSwiper/images/pic-or@2x-min.jpg


+ 9 - 0
src/components/PageSwiper/index.scss

@@ -0,0 +1,9 @@
+.page-swiper {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: url("./images/bg@2x-min.jpg") no-repeat center / cover;
+  z-index: 997;
+}

+ 7 - 0
src/components/PageSwiper/index.tsx

@@ -0,0 +1,7 @@
+import { View } from "@tarojs/components";
+import { FC } from "@tarojs/taro";
+import "./index.scss";
+
+export const PageSwiper: FC = () => {
+  return <View className="page-swiper"></View>;
+};

二進制
src/images/line-sights/16.png


二進制
src/images/line-sights/17.png


二進制
src/images/line-sights/18.png


二進制
src/images/line-sights/19.png


二進制
src/images/sights/16.png


二進制
src/images/sights/17.png


二進制
src/images/sights/18.png


二進制
src/images/sights/19.png


二進制
src/images/source-sights/16.jpg


二進制
src/images/source-sights/17.jpg


二進制
src/images/source-sights/18.jpg


二進制
src/images/source-sights/19.jpg


+ 34 - 15
src/pages/home/components/Menu/index.tsx

@@ -4,7 +4,9 @@ import Taro, { FC } from "@tarojs/taro";
 import { AtDrawer } from "taro-ui";
 import { AtDrawerProps } from "taro-ui/types/drawer";
 import { observer } from "mobx-react";
-import { getSceneUrl } from "../../../../utils";
+import { useMemo } from "react";
+import { getShopRuleApi } from "../../../../api";
+import { getSceneUrl, login } from "../../../../utils";
 import baseStore from "../../../../store/base";
 import CloseIcon from "../../../../images/icon_back_menu@2x.png";
 // import SearchIcon from "../../../../images/icon_search_black@2x-min.png";
@@ -17,7 +19,6 @@ import UserIcon from "../../../../images/icon_user_normal@2x-min.png";
 import ActUserIcon from "../../../../images/icon_user_active@2x-min.png";
 
 import "./index.scss";
-import { useMemo } from "react";
 
 export interface MenuProps extends AtDrawerProps {
   openSearch(): void;
@@ -94,7 +95,22 @@ export const Menu: FC<MenuProps> = observer((props) => {
           },
           {
             label: "爱心币商城",
-            link: "/subModule/pages/shopmall/index",
+            method: async () => {
+              const { display, rtf } = await getShopRuleApi();
+              if (display === 0) {
+                Taro.showToast({
+                  title: "商城暂未开启,敬请期待",
+                  icon: "none",
+                  duration: 3000,
+                });
+              } else {
+                baseStore.shopTips = rtf;
+
+                Taro.navigateTo({
+                  url: "/subModule/pages/shopmall/index",
+                });
+              }
+            },
             needAuth: true,
           },
         ],
@@ -103,6 +119,20 @@ export const Menu: FC<MenuProps> = observer((props) => {
     []
   );
 
+  const handleSubTab = async (subItem) => {
+    if (subItem.needAuth && !baseStore.isLogin) {
+      await login();
+    }
+
+    if (subItem.method) {
+      subItem.method();
+    } else {
+      Taro.navigateTo({
+        url: subItem.link,
+      });
+    }
+  };
+
   return (
     <AtDrawer {...props} className="menu" width={Taro.pxTransform(550)}>
       <Image
@@ -150,18 +180,7 @@ export const Menu: FC<MenuProps> = observer((props) => {
               {item.children.map((subItem) => (
                 <View
                   className="menu-item__sub"
-                  onClick={() => {
-                    if (subItem.method) {
-                      subItem.method();
-                    } else {
-                      Taro.navigateTo({
-                        url:
-                          subItem.needAuth && !baseStore.isLogin
-                            ? "/pages/login/index"
-                            : subItem.link,
-                      });
-                    }
-                  }}
+                  onClick={handleSubTab.bind(undefined, subItem)}
                 >
                   {subItem.label}
                 </View>

+ 9 - 2
src/pages/home/components/RoundItem/index.tsx

@@ -19,12 +19,14 @@ export interface RoundItemProps {
   minR: number;
   isActive: boolean;
   isNear: boolean;
+  onActLoaded: () => void;
+  onClick: () => void;
 }
 
 const IMG_BASE_URL = "https://houseoss.4dkankan.com/project/wx-csbwg-public";
 
 export const RoundItem: FC<RoundItemProps> = memo(
-  ({ id, angle, bigR, minR, isActive, isNear }) => {
+  ({ id, angle, bigR, minR, isActive, isNear, onClick, onActLoaded }) => {
     const [curAngle, setCurAngle] = useState(angle);
     const [actImgLoaded, setActImgLoaded] = useState(false);
     const _angle = useRef(angle);
@@ -81,6 +83,7 @@ export const RoundItem: FC<RoundItemProps> = memo(
           "is-near": isNear,
         })}
         style={style}
+        onClick={onClick}
       >
         <Image
           className={classNames("round-item__img", {
@@ -98,7 +101,11 @@ export const RoundItem: FC<RoundItemProps> = memo(
             )}
             mode="aspectFit"
             src={`${IMG_BASE_URL}/sights/${id}.png`}
-            onLoad={() => setActImgLoaded(true)}
+            onLoad={() => {
+              setActImgLoaded(true);
+              onActLoaded();
+            }}
+            onError={onActLoaded}
           />
         )}
       </View>

+ 7 - 0
src/pages/home/components/SearchLayout/index.scss

@@ -8,6 +8,13 @@
     height: 100vh;
     background-color: transparent;
   }
+  .at-input__icon {
+    margin-right: 20px;
+
+    &-close {
+      font-size: 44px;
+    }
+  }
   .layout-body {
     padding: 25px 40px;
     padding-bottom: constant(safe-area-inset-bottom);

+ 2 - 1
src/pages/home/components/SearchLayout/index.tsx

@@ -29,7 +29,7 @@ export const SearchLayout: FC<SearchLayoutProps> = (props) => {
     if (list[_idx]) return;
 
     const data = await getSignListApi({
-      region: CITY_LIST[_idx].title,
+      region: _idx === 0 ? "" : CITY_LIST[_idx].title,
       type: "scene",
     });
     setList({
@@ -63,6 +63,7 @@ export const SearchLayout: FC<SearchLayoutProps> = (props) => {
             className="search-input__input"
             name="keyword"
             value={input}
+            confirm-type="search"
             placeholder="请输入要搜索的内容..."
             onChange={(v) => {
               setInput(v as string);

+ 15 - 5
src/pages/home/components/SightDetailLayout/index.scss

@@ -9,15 +9,16 @@
     background-color: transparent;
   }
   .layout-body {
-    padding: 85px 55px;
-    padding-bottom: constant(safe-area-inset-bottom);
-    padding-bottom: env(safe-area-inset-bottom);
+    padding: 0;
+    // padding-bottom: constant(safe-area-inset-bottom);
+    // padding-bottom: env(safe-area-inset-bottom);
     max-height: unset;
     min-height: unset;
     height: 100%;
     box-sizing: border-box;
   }
   .layout-body__content {
+    position: relative;
     display: flex;
     flex-direction: column;
     max-height: unset;
@@ -25,6 +26,11 @@
     height: 100%;
   }
 
+  &-wrap {
+    padding: 85px 55px 210px;
+    height: 100%;
+    box-sizing: border-box;
+  }
   &-head {
     position: relative;
     display: flex;
@@ -66,7 +72,7 @@
   &-toolbar {
     display: flex;
     justify-content: center;
-    margin: 50px 0 40px;
+    margin-top: 50px;
     gap: 36px;
 
     &__btn {
@@ -82,6 +88,7 @@
   }
 
   &__text {
+    margin-top: 40px;
     color: white;
     font-size: 31px;
     line-height: 46px;
@@ -89,8 +96,11 @@
   }
 
   &__close {
-    margin-top: 140px;
+    position: absolute;
+    left: 50%;
+    bottom: 100px;
     width: 80px;
     height: 80px;
+    transform: translateX(-50%);
   }
 }

+ 56 - 51
src/pages/home/components/SightDetailLayout/index.tsx

@@ -2,7 +2,7 @@ import { useEffect, useMemo } from "react";
 import Taro, { FC } from "@tarojs/taro";
 import { AtFloatLayout } from "taro-ui";
 import { AtFloatLayoutProps } from "taro-ui/types/float-layout";
-import { Image, View } from "@tarojs/components";
+import { Image, ScrollView, View } from "@tarojs/components";
 import BorderImg from "../../../../images/line01@2x.png";
 import CloseIcon from "../../../../images/icon_back@2x-min.png";
 import { SIGHT_LIST } from "../../constants";
@@ -43,64 +43,69 @@ export const SightDetailLayout: FC<SightDetailLayoutProps> = (props) => {
 
   return (
     <AtFloatLayout className="sight-layout" {...props}>
-      <View className="sight-layout-head">
-        <View className="sight-layout-head__label">
+      <ScrollView scrollY className="sight-layout-wrap">
+        <View className="sight-layout-head">
+          <View className="sight-layout-head__label">
+            {/* @ts-ignore */}
+            {props.item.title || props.item.name}
+          </View>
           {/* @ts-ignore */}
-          {props.item.title || props.item.name}
-        </View>
-        <View>{props.item.address}</View>
+          <View>{props.item.region || props.item.address}</View>
 
-        <Image
-          src={BorderImg}
-          mode="widthFix"
-          className="sight-layout-head__bd"
-        />
-      </View>
+          <Image
+            src={BorderImg}
+            mode="widthFix"
+            className="sight-layout-head__bd"
+          />
+        </View>
 
-      <View className="sight-layout-main">
-        <Image
-          src={realUrl}
-          className="sight-layout__img"
-          mode="aspectFill"
-          onClick={handlePreview}
-        />
+        <View className="sight-layout-main">
+          <Image
+            src={realUrl}
+            className="sight-layout__img"
+            mode="aspectFill"
+            onClick={handlePreview}
+          />
 
-        <View className="sight-layout-toolbar">
-          {/* <View className="sight-layout-toolbar__btn">全景浏览</View> */}
+          {props.item.link && (
+            <View className="sight-layout-toolbar">
+              {/* <View className="sight-layout-toolbar__btn">全景浏览</View> */}
 
-          <View
-            className="sight-layout-toolbar__btn"
-            onClick={() => {
-              Taro.navigateTo({
-                url: `/subModule/pages/portrait-iframe/index?url=${encodeURIComponent(
-                  props.item.link
-                )}`,
-              });
-            }}
-          >
-            场景漫游
-          </View>
-        </View>
+              <View
+                className="sight-layout-toolbar__btn"
+                onClick={() => {
+                  Taro.navigateTo({
+                    url: `/subModule/pages/portrait-iframe/index?url=${encodeURIComponent(
+                      props.item.link
+                    )}`,
+                  });
+                }}
+              >
+                场景漫游
+              </View>
+            </View>
+          )}
 
-        {Array.isArray(props.item.content) ? (
-          props.item.content.map((i, idx) => (
-            <View className="sight-layout__text" key={idx}>
-              {i}
+          {Array.isArray(props.item.content) ? (
+            props.item.content.map((i, idx) => (
+              <View className="sight-layout__text" key={idx}>
+                {i}
+              </View>
+            ))
+          ) : (
+            <View className="sight-layout__text">
+              {/* @ts-ignore */}
+              {props.item.content || props.item.description}
             </View>
-          ))
-        ) : (
-          <View className="sight-layout__text">
-            {/* @ts-ignore */}
-            {props.item.content || props.item.description}
-          </View>
-        )}
+          )}
+        </View>
+      </ScrollView>
 
-        <Image
-          className="sight-layout__close"
-          src={CloseIcon}
-          onClick={props.onClose}
-        />
-      </View>
+      <Image
+        className="sight-layout__close"
+        src={CloseIcon}
+        onClick={props.onClose}
+      />
     </AtFloatLayout>
   );
 };

+ 14 - 16
src/pages/home/components/Swiper/index.tsx

@@ -14,6 +14,7 @@ import { SORT_MAP_ID } from "../../constants";
 
 export interface SwiperProps {
   curSwiperItem: number;
+  handleDetail(id: number): void;
   setCurSwiperItem(num: number): void;
 }
 
@@ -36,7 +37,7 @@ const getItemStack = () => {
 };
 
 export const Swiper = forwardRef<SwiperMethods, SwiperProps>(
-  ({ curSwiperItem, setCurSwiperItem }, ref) => {
+  ({ curSwiperItem, setCurSwiperItem, handleDetail }, ref) => {
     const [itemStack, setItemStack] = useState(getItemStack());
     const touchStartX = useRef(0);
     const moving = useRef(false);
@@ -79,8 +80,6 @@ export const Swiper = forwardRef<SwiperMethods, SwiperProps>(
       } else if (deltaX < -50) {
         toNext();
       }
-
-      setIsRunning(true);
     };
 
     const toggleHandler = (fn: Function) => {
@@ -89,11 +88,6 @@ export const Swiper = forwardRef<SwiperMethods, SwiperProps>(
       setIsRunning(false);
       moving.current = true;
       fn();
-
-      setIsRunning(true);
-      setTimeout(() => {
-        moving.current = false;
-      }, 800);
     };
 
     const toNext = () => {
@@ -140,14 +134,11 @@ export const Swiper = forwardRef<SwiperMethods, SwiperProps>(
     useInterval(toNext, isRunning ? 5000 : null);
 
     return (
-      <View className="sights">
-        <View
-          className="sights__panel"
-          catchMove
-          onTouchStart={handleTouchStart}
-          onTouchEnd={handleTouchEnd}
-        />
-
+      <View
+        className="sights"
+        onTouchStart={handleTouchStart}
+        onTouchEnd={handleTouchEnd}
+      >
         {itemStack.map((id, idx) => {
           const realId = SORT_MAP_ID[id + 1 > 25 ? 0 : id + 1];
           const show =
@@ -164,6 +155,13 @@ export const Swiper = forwardRef<SwiperMethods, SwiperProps>(
                 minR={MIN_R}
                 isActive={isActive}
                 isNear={nearIds.includes(id)}
+                onClick={handleDetail.bind(undefined, realId)}
+                onActLoaded={() => {
+                  setTimeout(() => {
+                    moving.current = false;
+                    setIsRunning(true);
+                  }, 500);
+                }}
               />
             )
           );

+ 31 - 38
src/pages/home/components/VisitCard/index.tsx

@@ -7,16 +7,16 @@ import { useState } from "react";
 import {
   createRandomString,
   getSceneUrl,
-  NICKNAME_key,
+  login,
+  NICKNAME_KEY,
   onValidateField,
-  TOKEN_KEY,
 } from "../../../../utils";
 import WechatIcon from "../../../../images/icon_wechat@2x-min.png";
 import {
+  handleVisitStateApi,
   setUserInfoApi,
   setVistorName,
   validateNickName,
-  wechatLoginApi,
 } from "../../../../api";
 import baseStore from "../../../../store/base";
 import Taro from "@tarojs/taro";
@@ -50,41 +50,39 @@ export const VisitCard: FC<VisitCardProps> = (props) => {
       return false;
     }
 
-    await validateNickName(name);
+    const reg = /[\u4e00-\u9fa5a-zA-Z]/g;
+    const matches = name.match(reg);
+
+    if (matches) {
+      await validateNickName(matches.join(""));
+    }
 
     return true;
   };
 
   const handleUserInfo = async () => {
-    // console.log(e);
     if (!(await handleValidate())) return;
 
-    Taro.login({
-      async success({ code }) {
-        try {
-          setWechatLoading(true);
-          Taro.showLoading({
-            title: "登陆中...",
-          });
-
-          const data = await wechatLoginApi(code);
-          Taro.setStorageSync(TOKEN_KEY, data.token);
-
-          await setUserInfoApi({
-            id: data.user.id,
-            nickName: name,
-          });
-
-          Taro.setStorageSync(NICKNAME_key, name);
-          baseStore.name = name;
-          baseStore.isLogin = true;
-          goHomePage();
-        } finally {
-          setWechatLoading(false);
-          Taro.hideLoading();
-        }
-      },
-    });
+    try {
+      setWechatLoading(true);
+
+      if (!baseStore.isLogin) {
+        await login();
+      }
+
+      await setUserInfoApi({
+        id: baseStore.userInfo.id,
+        nickName: name,
+      });
+      await handleVisitStateApi(1);
+
+      Taro.setStorageSync(NICKNAME_KEY, name);
+      baseStore.name = name;
+      baseStore.userInfo.invite = 1;
+      goHomePage();
+    } finally {
+      setWechatLoading(false);
+    }
   };
 
   const handleVisitor = async () => {
@@ -92,18 +90,14 @@ export const VisitCard: FC<VisitCardProps> = (props) => {
       if (!(await handleValidate())) return;
 
       setLoading(true);
-      Taro.showLoading({
-        title: "登陆中...",
-      });
 
       await setVistorName(name);
 
-      Taro.setStorageSync(NICKNAME_key, name);
+      Taro.setStorageSync(NICKNAME_KEY, name);
       baseStore.name = name;
       goHomePage();
     } finally {
       setLoading(false);
-      Taro.hideLoading();
     }
   };
 
@@ -161,8 +155,7 @@ export const VisitCard: FC<VisitCardProps> = (props) => {
       <AtButton
         loading={wechatLoading}
         className="visit-card__wechat"
-        openType="getUserInfo"
-        onGetUserInfo={handleUserInfo}
+        onClick={handleUserInfo}
       >
         <Image className="visit-card__wechat__icon" src={WechatIcon} />
         成为云城居民

+ 9 - 5
src/pages/home/constants.ts

@@ -1,14 +1,18 @@
 export const CITY_LIST = [
   {
     id: 0,
-    title: "江阴市",
+    title: "全部",
   },
   {
     id: 1,
-    title: "宜兴市",
+    title: "江阴市",
   },
   {
     id: 2,
+    title: "宜兴市",
+  },
+  {
+    id: 3,
     title: "梁溪区",
   },
   {
@@ -20,15 +24,15 @@ export const CITY_LIST = [
     title: "惠山区",
   },
   {
-    id: 3,
+    id: 6,
     title: "滨湖区",
   },
   {
-    id: 6,
+    id: 7,
     title: "新吴区",
   },
   {
-    id: 7,
+    id: 8,
     title: "经开区",
   },
 ];

+ 3 - 1
src/pages/home/index.config.ts

@@ -1 +1,3 @@
-export default definePageConfig({});
+export default definePageConfig({
+  enableShareAppMessage: true,
+});

+ 23 - 10
src/pages/home/index.scss

@@ -26,13 +26,9 @@
   &__cloud {
     position: absolute;
     left: -100%;
-    bottom: 0;
-    height: 148px;
-    animation: cloudMove linear 8s infinite;
-
-    &.cloud2 {
-      animation-delay: 4s;
-    }
+    bottom: -260px;
+    width: 100%;
+    animation: cloudMove linear 60s infinite;
   }
   &-container {
     position: relative;
@@ -203,14 +199,20 @@
       }
     }
   }
+  &__search {
+    position: fixed;
+    top: 42px;
+    right: 33px;
+    width: 40px;
+    height: 40px;
+    z-index: 9;
+  }
 }
 
 .home2 {
   position: relative;
   height: 100vh;
   overflow: hidden;
-  background: url("https://houseoss.4dkankan.com/project/wx-csbwg-public/images/bg_loading%402x-min.png")
-    no-repeat center / cover;
 
   &__btn {
     position: absolute;
@@ -218,6 +220,14 @@
     bottom: 150px;
     width: 496px;
     transform: translateX(-50%);
+    z-index: 2;
+  }
+  &__bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
   }
 }
 
@@ -268,7 +278,10 @@
 }
 
 @keyframes cloudMove {
+  50% {
+    left: 0;
+  }
   100% {
-    left: 100%;
+    left: -100%;
   }
 }

+ 60 - 49
src/pages/home/index.tsx

@@ -17,7 +17,6 @@ import Taro, {
 } from "@tarojs/taro";
 import { Menu } from "./components/Menu";
 import BtmBgImg from "../../images/img_city-min.png";
-import BgImg from "../../images/img_map@2x-min.jpg";
 import CloudImg from "../../images/img_cloud-min.png";
 import LeftIcon from "../../images/icon_blue_left@2x-min.png";
 import RightIcon from "../../images/icon_blue_right@2x-min.png";
@@ -26,10 +25,12 @@ import { Swiper as SightSwiper, SwiperMethods } from "./components/Swiper";
 import { SearchLayout } from "./components/SearchLayout";
 import { SightDetailLayout } from "./components/SightDetailLayout";
 import { SIGHT_LIST, SORT_MAP_ID } from "./constants";
-import { checkLoginApi, getSignListApi } from "../../api";
+import { getSignListApi } from "../../api";
 import { VisitCard } from "./components/VisitCard";
-import { getSceneUrl, NICKNAME_key, TOKEN_KEY } from "../../utils";
+import { getSceneUrl, login } from "../../utils";
 import baseStore from "../../store/base";
+import SearchIcon from "../../images/icon_search_white@2x-min.png";
+import { PageSwiper } from "../../components/PageSwiper";
 import "./index.scss";
 
 const PointIcon = memo(() => {
@@ -76,14 +77,19 @@ const HomePage: FC = () => {
     [curSwiperItem]
   );
 
-  const openSearch = () => {
-    setShowMenu(false);
+  const openSearch = (closeMenu?: boolean) => {
+    closeMenu && setShowMenu(false);
     setShowSearch(true);
+    if (!closeMenu) {
+      swiperRef.current?.setIsRunning(false);
+    }
   };
 
-  const handleDetail = async () => {
+  const handleDetail = async (id?: number) => {
     swiperRef.current?.setIsRunning(false);
-    const target = SIGHT_LIST.find((i) => i.id === SORT_MAP_ID[curSwiperItem]);
+    const target = SIGHT_LIST.find(
+      (i) => i.id === (id || SORT_MAP_ID[curSwiperItem])
+    );
     const data = await getSignListApi({
       searchKey: target?.title,
       type: "scene",
@@ -113,29 +119,6 @@ const HomePage: FC = () => {
     });
   };
 
-  const checkLogin = async () => {
-    try {
-      Taro.showLoading({
-        title: "登录中...",
-      });
-      const data = await checkLoginApi();
-
-      if (data) {
-        baseStore.isLogin = true;
-        Taro.navigateTo({
-          url:
-            "/subModule/pages/iframe/index?url=" +
-            encodeURIComponent(getSceneUrl()),
-        });
-      } else {
-        Taro.removeStorageSync(TOKEN_KEY);
-        Taro.removeStorageSync(NICKNAME_key);
-      }
-    } finally {
-      Taro.hideLoading();
-    }
-  };
-
   useDidShow(() => {
     loaded && swiperRef.current?.setIsRunning(true);
   });
@@ -153,7 +136,17 @@ const HomePage: FC = () => {
         }}
       />
 
-      <Menu show={showMenu} onClose={closeMenu} openSearch={openSearch} />
+      <Menu
+        show={showMenu}
+        onClose={closeMenu}
+        openSearch={openSearch.bind(undefined, true)}
+      />
+
+      <Image
+        src={SearchIcon}
+        className="home__search"
+        onClick={() => openSearch()}
+      />
 
       <Swiper
         vertical
@@ -188,6 +181,7 @@ const HomePage: FC = () => {
                 ref={swiperRef}
                 curSwiperItem={curSwiperItem}
                 setCurSwiperItem={setCurSwiperItem}
+                handleDetail={handleDetail}
               />
 
               <View className="home-toggle">
@@ -207,7 +201,7 @@ const HomePage: FC = () => {
 
                   <View
                     className="home-toggle__detail"
-                    onClick={handleDetail}
+                    onClick={() => handleDetail()}
                   />
                 </View>
 
@@ -228,23 +222,14 @@ const HomePage: FC = () => {
 
             <Image
               className="home__bg"
-              src={BgImg}
+              src="https://houseoss.4dkankan.com/project/wx-csbwg-public/images/img_map%402x-min.jpg"
               mode="widthFix"
               style={{
                 top: `${-offsetHeight}px`,
               }}
             />
             <Image className="home__btm-bg" src={BtmBgImg} mode="widthFix" />
-            <Image
-              className="home__cloud cloud1"
-              src={CloudImg}
-              mode="heightFix"
-            />
-            <Image
-              className="home__cloud cloud2"
-              src={CloudImg}
-              mode="heightFix"
-            />
+            <Image className="home__cloud" src={CloudImg} mode="heightFix" />
           </View>
         </SwiperItem>
 
@@ -253,16 +238,35 @@ const HomePage: FC = () => {
             className="home2__btn"
             src={ButtonImg}
             mode="widthFix"
-            onClick={() => {
-              const token = Taro.getStorageSync(TOKEN_KEY);
+            onClick={async () => {
+              const userInfo = baseStore.userInfo;
 
-              if (token) {
-                checkLogin();
-              } else {
+              if (!userInfo) {
+                await login();
+              }
+
+              if (userInfo.invite === 0) {
                 setVisitVisible(true);
+                return;
               }
+
+              Taro.navigateTo({
+                url:
+                  "/subModule/pages/iframe/index?url=" +
+                  encodeURIComponent(getSceneUrl()),
+              });
             }}
           />
+
+          <Video
+            className="home2__bg"
+            src="https://houseoss.4dkankan.com/project/wx-csbwg-public/videos/city.mp4"
+            autoplay
+            muted
+            loop
+            controls={false}
+            objectFit="cover"
+          />
         </SwiperItem>
       </Swiper>
 
@@ -284,7 +288,12 @@ const HomePage: FC = () => {
 
       <SearchLayout
         isOpened={showSearch}
-        onClose={() => setShowSearch(false)}
+        onClose={() => {
+          setShowSearch(false);
+          if (curSwiper === 0) {
+            swiperRef.current?.setIsRunning(true);
+          }
+        }}
         openDetail={(item) => {
           swiperRef.current?.setIsRunning(false);
           setItem(item);
@@ -304,6 +313,8 @@ const HomePage: FC = () => {
         isOpened={visitVisible}
         onClose={() => setVisitVisible(false)}
       />
+
+      {/* <PageSwiper /> */}
     </>
   );
 };

+ 4 - 4
src/pages/login/index.tsx

@@ -4,7 +4,7 @@ import { AtButton, AtForm, AtInput } from "taro-ui";
 import classNames from "classnames";
 import { useEffect, useState } from "react";
 import {
-  NICKNAME_key,
+  NICKNAME_KEY,
   TOKEN_KEY,
   createRandomString,
   onValidateField,
@@ -71,7 +71,7 @@ const LoginPage: FC = () => {
             nickName: name,
           });
 
-          Taro.setStorageSync(NICKNAME_key, name);
+          Taro.setStorageSync(NICKNAME_KEY, name);
           baseStore.name = name;
           baseStore.isLogin = true;
           goHomePage();
@@ -94,7 +94,7 @@ const LoginPage: FC = () => {
 
       await setVistorName(name);
 
-      Taro.setStorageSync(NICKNAME_key, name);
+      Taro.setStorageSync(NICKNAME_KEY, name);
       baseStore.name = name;
       goHomePage();
     } finally {
@@ -115,7 +115,7 @@ const LoginPage: FC = () => {
         goHomePage();
       } else {
         Taro.removeStorageSync(TOKEN_KEY);
-        Taro.removeStorageSync(NICKNAME_key);
+        Taro.removeStorageSync(NICKNAME_KEY);
       }
     } finally {
       Taro.hideLoading();

+ 5 - 2
src/store/base.ts

@@ -1,10 +1,13 @@
 import Taro from "@tarojs/taro";
 import { observable } from "mobx";
-import { NICKNAME_key } from "../utils";
+import { NICKNAME_KEY, USER_INFO_KEY } from "../utils";
 
 const baseStore = observable({
-  name: Taro.getStorageSync(NICKNAME_key) ?? "",
+  name: Taro.getStorageSync(NICKNAME_KEY) ?? "",
+  userInfo: Taro.getStorageSync(USER_INFO_KEY),
   isLogin: false,
+
+  shopTips: "",
 });
 
 export default baseStore;

+ 2 - 0
src/subModule/pages/feedback/index.tsx

@@ -63,6 +63,7 @@ const FeedBackPage: FC = () => {
             <AtInput
               name="name"
               className="feedback__input"
+              maxLength={20}
               placeholder="请输入内容,20字以内"
               value={params.name}
               onChange={(val) =>
@@ -78,6 +79,7 @@ const FeedBackPage: FC = () => {
               name="phone"
               type="phone"
               className="feedback__input"
+              maxLength={20}
               placeholder="请输入内容,20字以内"
               value={params.phone}
               onChange={(val) =>

+ 5 - 3
src/subModule/pages/order/index.tsx

@@ -43,8 +43,8 @@ const OrderPage: FC = () => {
           });
 
           Taro.showToast({
-            title: "兑换成功",
-            icon: "success",
+            title: "提交成功,工作人员会与您及时联系",
+            icon: "none",
             duration: 3000,
           });
 
@@ -69,6 +69,7 @@ const OrderPage: FC = () => {
               className="feedback__input"
               placeholder="请输入内容,20字以内"
               value={params.name}
+              maxLength={20}
               onChange={(val) =>
                 setParams({
                   ...params,
@@ -81,6 +82,7 @@ const OrderPage: FC = () => {
             <AtInput
               name="phone"
               type="phone"
+              maxLength={20}
               className="feedback__input"
               placeholder="请输入内容,20字以内"
               value={params.phone}
@@ -101,7 +103,7 @@ const OrderPage: FC = () => {
               onChange={(val) =>
                 setParams({
                   ...params,
-                  description: val,
+                  description: val.trim(),
                 })
               }
             />

+ 4 - 0
src/subModule/pages/shopmall/components/Products/index.scss

@@ -3,6 +3,10 @@
   flex-wrap: wrap;
   margin: 40px 0;
 
+  &-wrap {
+    flex: 1;
+    height: 0;
+  }
   &-item {
     margin: 8px;
     padding: 0 8px 8px;

+ 38 - 32
src/subModule/pages/shopmall/components/Products/index.tsx

@@ -1,6 +1,6 @@
-import { Image, Text, View } from "@tarojs/components";
-import Taro, { FC, useReachBottom } from "@tarojs/taro";
-import { useEffect, useRef, useState } from "react";
+import { Image, ScrollView, Text, View } from "@tarojs/components";
+import Taro, { FC, useDidShow } from "@tarojs/taro";
+import { useRef, useState } from "react";
 import BuyIcon from "../../../../images/icon_presents@2x-min.png";
 import { getProductListApi } from "../../../../../api";
 import { getBaseURL } from "@dage/service";
@@ -16,7 +16,7 @@ export interface ProductsProps {
   point: number;
 }
 
-export const Products: FC<ProductsProps> = ({ curTab, point }) => {
+export const Products: FC<ProductsProps> = ({ point }) => {
   const params = useRef({
     pageNum: 1,
     pageSize: 20,
@@ -42,12 +42,10 @@ export const Products: FC<ProductsProps> = ({ curTab, point }) => {
     params.current.pageNum += 1;
   };
 
-  useEffect(() => {
+  useDidShow(() => {
+    params.current.pageNum = 1;
+    hasMore.current = true;
     getProductList();
-  }, []);
-
-  useReachBottom(() => {
-    curTab === 0 && getProductList();
   });
 
   const handleBuy = (item: any) => {
@@ -66,31 +64,39 @@ export const Products: FC<ProductsProps> = ({ curTab, point }) => {
   };
 
   return (
-    <View className="products">
-      {list.map((item) => (
-        <View key={item.id} className="products-item">
-          <Image
-            className="products-item__img"
-            src={`${baseUrl}${item.thumb}`}
-            mode="aspectFill"
-          />
-
-          <View className="products-item__main">
-            <View className="products-item__title limit-line">{item.name}</View>
-            <View className="products-item__stock">库存:{item.stock}</View>
-            <View className="products-item__ft">
-              <Text className="products-item__ft__price">{item.score}</Text>
-              <Text>爱心币</Text>
-            </View>
-
+    <ScrollView
+      scrollY
+      className="products-wrap"
+      onScrollToLower={getProductList}
+    >
+      <View className="products">
+        {list.map((item) => (
+          <View key={item.id} className="products-item">
             <Image
-              className="products-item__buy"
-              src={BuyIcon}
-              onClick={handleBuy.bind(undefined, item)}
+              className="products-item__img"
+              src={`${baseUrl}${item.thumb}`}
+              mode="aspectFill"
             />
+
+            <View className="products-item__main">
+              <View className="products-item__title limit-line">
+                {item.name}
+              </View>
+              <View className="products-item__stock">库存:{item.stock}</View>
+              <View className="products-item__ft">
+                <Text className="products-item__ft__price">{item.score}</Text>
+                <Text>爱心币</Text>
+              </View>
+
+              <Image
+                className="products-item__buy"
+                src={BuyIcon}
+                onClick={handleBuy.bind(undefined, item)}
+              />
+            </View>
           </View>
-        </View>
-      ))}
-    </View>
+        ))}
+      </View>
+    </ScrollView>
   );
 };

+ 12 - 0
src/subModule/pages/shopmall/components/Records/index.scss

@@ -1,5 +1,17 @@
 .records {
+  flex: 1;
   padding: 20px 0;
+  height: 0;
+  box-sizing: border-box;
+
+  &-tips {
+    padding: 0 20px;
+    color: #589498;
+    text-align: center;
+    font-size: 23px;
+    height: 50px;
+    line-height: 50px;
+  }
 
   &-item {
     display: flex;

+ 36 - 17
src/subModule/pages/shopmall/components/Records/index.tsx

@@ -1,6 +1,7 @@
-import { View } from "@tarojs/components";
-import { FC } from "@tarojs/taro";
+import { View, Text, ScrollView } from "@tarojs/components";
+import { FC, pxTransform } from "@tarojs/taro";
 import classNames from "classnames";
+import baseStore from "../../../../../store/base";
 import "./index.scss";
 
 export interface RecordsProps {
@@ -9,24 +10,42 @@ export interface RecordsProps {
 
 export const Records: FC<RecordsProps> = ({ list }) => {
   return (
-    <View className="records">
-      {!list.length && <View className="records__nomore">暂无记录</View>}
+    <>
+      <ScrollView scrollY className="records">
+        {!list.length && <View className="records__nomore">暂无记录</View>}
 
-      {list.map((item) => (
-        <View key={item.id} className="records-item">
-          <View className="records-item__lf">
-            <View className="records-item__lf__label">{item.type}</View>
-            <View className="records-item__lf__date">{item.createTime}</View>
-          </View>
+        {list.map((item) => (
+          <View key={item.id} className="records-item">
+            <View className="records-item__lf">
+              <View className="records-item__lf__label">{item.type}</View>
+              <View className="records-item__lf__date">
+                {item.createTime}
+
+                {item.prizeName && (
+                  <Text style={{ paddingLeft: pxTransform(20) }}>
+                    {item.prizeName}
+                  </Text>
+                )}
+              </View>
+            </View>
 
-          <View
-            className={classNames("records-item__rg", { red: item.score < 0 })}
-          >
-            {item.score > 0 ? "+" : ""}
-            {item.score}
+            <View
+              className={classNames("records-item__rg", {
+                red: item.score < 0,
+              })}
+            >
+              {item.score > 0 ? "+" : ""}
+              {item.score}
+            </View>
           </View>
+        ))}
+      </ScrollView>
+
+      {baseStore.shopTips && (
+        <View className="records-tips padding-safe-area-bottom">
+          如有疑问,请咨询 {baseStore.shopTips}
         </View>
-      ))}
-    </View>
+      )}
+    </>
   );
 };

+ 15 - 0
src/subModule/pages/shopmall/index.scss

@@ -48,6 +48,12 @@
   }
 
   &-tab {
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: flex;
+    flex-direction: column;
+
     .at-tabs__header {
       margin: 0 auto;
       width: calc(100% - 42px);
@@ -83,5 +89,14 @@
         font-family: "Source Han Sans CN-Bold";
       }
     }
+    .at-tabs__body {
+      flex: 1;
+      height: 0;
+    }
+    .at-tabs-pane {
+      display: inline-flex;
+      flex-direction: column;
+      height: 100% !important;
+    }
   }
 }

+ 33 - 2
src/utils/index.ts

@@ -1,11 +1,14 @@
 import Taro, { getStorageSync } from "@tarojs/taro";
 import Schema, { Rules } from "async-validator";
+import baseStore from "../store/base";
+import { wechatLoginApi } from "../api";
 
 export const TOKEN_KEY = "token";
-export const NICKNAME_key = "nickname";
+export const NICKNAME_KEY = "nickname";
+export const USER_INFO_KEY = "userinfo";
 
 export const getSceneUrl = (scene?: number) => {
-  const name = getStorageSync(NICKNAME_key);
+  const name = getStorageSync(NICKNAME_KEY);
   const token = getStorageSync(TOKEN_KEY);
 
   return `https://app.4dage.com/projects/wxcs/web/index.html?platform=wx&name=${name}&token=${token}${
@@ -75,3 +78,31 @@ export function debounce(func: Function, time: number, immediate = false) {
     }
   };
 }
+
+export const login = () => {
+  return new Promise((res, rej) => {
+    Taro.login({
+      async success({ code }) {
+        try {
+          Taro.showLoading({
+            title: "登陆中...",
+          });
+
+          const data = await wechatLoginApi(code);
+          Taro.setStorageSync(TOKEN_KEY, data.token);
+          Taro.setStorageSync(USER_INFO_KEY, data.user);
+
+          baseStore.isLogin = true;
+          baseStore.userInfo = data.user;
+          baseStore.name = data.user.nickName;
+          res(data);
+        } finally {
+          Taro.hideLoading();
+        }
+      },
+      fail(err) {
+        rej(err);
+      },
+    });
+  });
+};

二進制
src/videos/city.mp4