周杰伦 4 years ago
parent
commit
84aaf479fc
69 changed files with 2441 additions and 56 deletions
  1. 32 0
      src/api/auth.ts
  2. 43 0
      src/api/qrcode.ts
  3. 86 0
      src/api/user.ts
  4. 30 1
      src/app.config.ts
  5. BIN
      src/assets/AddBaby/arrow.png
  6. BIN
      src/assets/AuthResult/bg.png
  7. BIN
      src/assets/AuthResult/book.png
  8. BIN
      src/assets/AuthResult/book1.png
  9. BIN
      src/assets/AuthResult/chapter.png
  10. BIN
      src/assets/AuthResult/dog.png
  11. BIN
      src/assets/ScanQrcode/hava-already.png
  12. BIN
      src/assets/ScanQrcode/query-faild.png
  13. BIN
      src/assets/ScanQrcode/scan-icon.png
  14. BIN
      src/assets/ScanQrcode/shop.png
  15. BIN
      src/assets/ScanResult/getSuccess.png
  16. BIN
      src/assets/ScanResult/result0.png
  17. BIN
      src/assets/ScanResult/result1.png
  18. BIN
      src/assets/ScanResult/result2.png
  19. BIN
      src/assets/ScanResult/reuslt-bg.png
  20. BIN
      src/assets/authOpra/scan-icon.png
  21. BIN
      src/assets/authOpra/type0.png
  22. BIN
      src/assets/authOpra/type1.png
  23. BIN
      src/assets/authOpra/type2.png
  24. BIN
      src/assets/authOpra/type3.png
  25. BIN
      src/assets/authOpra/type4.png
  26. BIN
      src/assets/authQuery/auth-bg.png
  27. BIN
      src/assets/authQuery/auth0.png
  28. BIN
      src/assets/authQuery/auth1.png
  29. BIN
      src/assets/authQuery/auth2.png
  30. BIN
      src/assets/authQuery/auth3.png
  31. BIN
      src/assets/authQuery/auth4.png
  32. BIN
      src/assets/authQuery/three-step.png
  33. BIN
      src/assets/home/bg.png
  34. BIN
      src/assets/home/home0.png
  35. BIN
      src/assets/home/home1.png
  36. BIN
      src/assets/home/qrcode.png
  37. 3 0
      src/pages/AddBaby/index.config.ts
  38. 87 0
      src/pages/AddBaby/index.scss
  39. 240 0
      src/pages/AddBaby/index.tsx
  40. 3 0
      src/pages/AuthOpra/index.config.ts
  41. 92 0
      src/pages/AuthOpra/index.scss
  42. 149 0
      src/pages/AuthOpra/index.tsx
  43. 4 0
      src/pages/AuthQuery/index.config.ts
  44. 30 0
      src/pages/AuthQuery/index.scss
  45. 54 0
      src/pages/AuthQuery/index.tsx
  46. 3 0
      src/pages/AuthResult/index.config.ts
  47. 113 0
      src/pages/AuthResult/index.scss
  48. 44 0
      src/pages/AuthResult/index.tsx
  49. 3 0
      src/pages/QueryRecord/index.config.ts
  50. 64 0
      src/pages/QueryRecord/index.scss
  51. 85 0
      src/pages/QueryRecord/index.tsx
  52. 19 0
      src/pages/ScanQrcode/data.d.ts
  53. 3 0
      src/pages/ScanQrcode/index.config.ts
  54. 179 0
      src/pages/ScanQrcode/index.scss
  55. 176 0
      src/pages/ScanQrcode/index.tsx
  56. 12 0
      src/pages/ScanResult/data.d.ts
  57. 3 0
      src/pages/ScanResult/index.config.ts
  58. 215 0
      src/pages/ScanResult/index.scss
  59. 213 0
      src/pages/ScanResult/index.tsx
  60. 3 0
      src/pages/ShopCate/index.config.ts
  61. 35 0
      src/pages/ShopCate/index.scss
  62. 62 0
      src/pages/ShopCate/index.tsx
  63. 8 0
      src/pages/home/index.scss
  64. 142 4
      src/pages/home/index.tsx
  65. 35 1
      src/pages/index/index.scss
  66. 83 19
      src/pages/index/index.tsx
  67. 21 3
      src/service/config.ts
  68. 65 28
      src/service/request.ts
  69. 2 0
      src/utils/tip.ts

+ 32 - 0
src/api/auth.ts

@@ -0,0 +1,32 @@
+import { request } from '../service/request'
+
+/**
+ * 查询证书
+ */
+
+type getAuthType = {
+    label: string,
+    typeId: number
+}
+
+export const queryCertificate = (data: getAuthType) => {
+    return request({
+        url: `/verify/certificate`,
+        data
+    })
+}
+
+
+type queryCertificateFileType = {
+    fileUrl: string,
+    typeId: number
+}
+
+export const queryCertificateFile = (data: queryCertificateFileType) => {
+    return request({
+        url: `/verify/certificate/file`,
+        data
+    })
+}
+
+

+ 43 - 0
src/api/qrcode.ts

@@ -0,0 +1,43 @@
+import { request } from '../service/request'
+
+// 二维码验证
+
+export const authQrcode = (code: string) => {
+    return request({
+        url: `/v2/verify/code/verify/${code}`
+    })
+}
+
+
+/**
+ * 获取查询记录
+ * @param { pageSize } 默认10
+ * @param { page } 页码
+ * @param { type } 0 假码 1 真码 其他为全部
+ * 
+ */
+
+ type getRecordType = {
+    page: number,
+    pageSize?: number,
+    type?: number
+ }
+
+
+export const getRecord = (data: getRecordType = {pageSize: 10, page: 1, type: 2} )=> {
+    return request({
+            url: '/verify/user/scanCodeRecord',
+            data
+        })
+    }
+
+/***
+ *  获取商品  --> 老版的二维码使用
+ */
+export const getGoodsList = () =>   {
+    return request({
+        url:'/verify/getAllProduct',
+    })
+}
+
+

+ 86 - 0
src/api/user.ts

@@ -0,0 +1,86 @@
+import { request } from '../service/request'
+
+/**
+ * 
+ * token 失效 刷新token使用
+ * @param { string } code  Taro.login 的返回值
+ */
+export const reloadlogin = (code: string) => {
+    return request({
+        url: `/verify/user/againLogin/${code}`,
+        method: 'POST'
+    })
+}
+
+
+// 获取用户手机号
+export type getUserPhoneType = {
+    code: string,
+    encryptedData: string,
+    iv: string
+}
+
+export const getUserPhoneNumber = (params: getUserPhoneType) => {
+    const {code, encryptedData, iv } = params
+    return request({
+        url: `/verify/bindPhoneNumberV3/${code}`,
+        method: 'POST',
+        data: {
+            encryptedData,
+            iv
+        }
+    })
+}
+
+
+
+// 获取用户宝贝信息
+
+export const getBaby = () => {
+    return request({
+        url: `/baby`
+    })
+}
+
+
+// 添加宝贝
+type postBabyType = {
+    img: string,
+    gender: number | string,
+    birthday: string,
+    relation: string,
+    name: string,
+    relationName: string,
+}
+
+export const postBaby = (data: postBabyType) => {
+    return request({
+        url: `/baby`,
+        method: 'POST',
+        data
+    })
+}
+
+// 获取亲属关系
+export const getRelation = () => {
+    return request({
+        url: `/baby/relation`
+    })
+}
+
+
+
+// 领取指导手册
+
+type getManualType = {
+    babyId: string,
+    goodsTypePdfId: string
+}
+
+export const getManual = (data: getManualType[]) => {
+    return request({
+        url: `/v1/goodsTypePdf/receiveRecord`,
+        method: 'POST',
+        data
+    })
+}

+ 30 - 1
src/app.config.ts

@@ -1,7 +1,36 @@
 export default {
   pages: [
-    'pages/index/index'
+    'pages/index/index',
+    'pages/AuthQuery/index',
+    'pages/ScanQrcode/index',
+    'pages/AuthOpra/index',
+    'pages/ScanResult/index',
+    'pages/Home/index',
+    'pages/AddBaby/index',
+    'pages/QueryRecord/index',
+    'pages/ShopCate/index',
+    'pages/AuthResult/index',
   ],
+  // "subpackages": [
+  //   {
+  //     "root": "pages/AddBaby",
+  //     "pages": [
+  //       'index'
+  //     ]
+  //   },
+  //   {
+  //     "root": "pages/AuthOpra",
+  //     "pages": [
+  //       'index'
+  //     ]
+  //   },
+  //   {
+  //     "root": "pages/ShopCate",
+  //     "pages": [
+  //       'index'
+  //     ]
+  //   },
+  // ],
   window: {
     backgroundTextStyle: 'light',
     navigationBarBackgroundColor: '#fff',

BIN
src/assets/AddBaby/arrow.png


BIN
src/assets/AuthResult/bg.png


BIN
src/assets/AuthResult/book.png


BIN
src/assets/AuthResult/book1.png


BIN
src/assets/AuthResult/chapter.png


BIN
src/assets/AuthResult/dog.png


BIN
src/assets/ScanQrcode/hava-already.png


BIN
src/assets/ScanQrcode/query-faild.png


BIN
src/assets/ScanQrcode/scan-icon.png


BIN
src/assets/ScanQrcode/shop.png


BIN
src/assets/ScanResult/getSuccess.png


BIN
src/assets/ScanResult/result0.png


BIN
src/assets/ScanResult/result1.png


BIN
src/assets/ScanResult/result2.png


BIN
src/assets/ScanResult/reuslt-bg.png


BIN
src/assets/authOpra/scan-icon.png


BIN
src/assets/authOpra/type0.png


BIN
src/assets/authOpra/type1.png


BIN
src/assets/authOpra/type2.png


BIN
src/assets/authOpra/type3.png


BIN
src/assets/authOpra/type4.png


BIN
src/assets/authQuery/auth-bg.png


BIN
src/assets/authQuery/auth0.png


BIN
src/assets/authQuery/auth1.png


BIN
src/assets/authQuery/auth2.png


BIN
src/assets/authQuery/auth3.png


BIN
src/assets/authQuery/auth4.png


BIN
src/assets/authQuery/three-step.png


BIN
src/assets/home/bg.png


BIN
src/assets/home/home0.png


BIN
src/assets/home/home1.png


BIN
src/assets/home/qrcode.png


+ 3 - 0
src/pages/AddBaby/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '宝宝信息'
+}

+ 87 - 0
src/pages/AddBaby/index.scss

@@ -0,0 +1,87 @@
+@import "~taro-ui/dist/style/components/action-sheet.scss";
+@import "~taro-ui/dist/style/components/list.scss";
+@import "~taro-ui/dist/style/components/float-layout.scss";
+.AddBaby {
+    
+}
+
+.form {
+    padding: 0px 26px 0px 22px;
+    box-sizing: border-box;
+    .item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        border-bottom: 2px solid #F6F6F6;
+        height: 98px;
+        .label {
+            font-size: 28px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #999999;
+        }
+        .content {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            .text {
+                font-size: 28px;
+                font-family: PingFangSC-Regular, PingFang SC;
+                font-weight: 400;
+                color: #333333;
+                margin-right: 6px;
+            }
+        }
+    }
+}
+
+.ava {
+    height: 180px;
+}
+
+.ava-img {
+    width: 120px;
+    height: 120px;
+    background-color: #e8e8e8;
+    border-radius: 50%;
+}
+
+.name {
+    text-align: right;
+    font-size: 28px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #333333;
+    margin-right: 6px;
+}
+
+.relation {
+    height: 600px;
+    .sheetItem {
+        text-align: center;
+    }
+}
+
+.placeholderClass {
+    font-size: 28px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #333333;
+}
+
+.button {
+    font-size: 28px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #fff;
+    width: 152px;
+    height: 60px;
+    background-color:  #002F95;
+    box-shadow: 0px 4px 8px 0px rgba(0, 47, 149, 0.4);
+    border-radius: 44px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin: 0 auto;
+    margin-top: 160px;
+}

+ 240 - 0
src/pages/AddBaby/index.tsx

@@ -0,0 +1,240 @@
+import React, { useState, useEffect } from 'react'
+
+import { View, Image, Picker  } from '@tarojs/components'
+
+import { AtInput, AtActionSheet, AtActionSheetItem, AtFloatLayout} from 'taro-ui'
+
+import Taro from '@tarojs/taro'
+
+import { postBaby, getRelation } from '../../api/user'
+
+import Tip from '../../utils/tip'
+
+import './index.scss'
+
+const switchGender = (type) => {
+    switch (type) {
+        case 1:
+            return '男'
+        case 2:
+            return '女'
+        default:
+            return '未填写'
+
+    }
+}
+
+const AddBaby: React.FC = () => {
+
+    const [itemType, setItemType] = useState<number>(0)
+
+    const [ visible, setVisible] = useState<boolean>(false)
+
+    const [ relationList, setRelationList] = useState<Record<string, any>[]>([]) 
+
+    const [ relationName, setRelationName ]  = useState<string>('未填写')
+
+    const [ birthday, setBirthday ] = useState<string>('未填写')
+
+    const [ gender, setGender] = useState<number | string>('未填写')
+
+    const changeBirthday = (e) => setBirthday(e.detail.value)
+
+    const [img, setImg] = useState<string>('') 
+
+    const [ name, setName] = useState<string>('')
+
+    const [relation, setRelation] = useState<string>('')
+
+    // 名字
+    const changeName = (e) => setName(e)
+
+    // 宝宝头像
+    const changeAva = () => {
+        Taro.chooseImage({
+            success: (chooseImageRes) => {
+                const tempFilePaths = chooseImageRes.tempFilePaths;
+                Taro.uploadFile({
+                    url: 'http://training.luojigou.vip/training/file/uploadFile',
+                    filePath: tempFilePaths[0],
+                    name: 'file',
+                    formData: {
+                        'user': 'test'
+                    },
+                    success: (uploadFileRes) => {
+                        console.log(JSON.parse(uploadFileRes.data).data);
+                        setImg(JSON.parse(uploadFileRes.data).data)
+                    }
+                });
+            }
+        });
+    }
+
+    // 性别
+    const changeGender = (value: number) => {
+        setGender(value)
+        setVisible(false)
+    }
+
+    // 选择亲属关系
+    const changeRelation = (item: Record<string, any>) => {
+        setRelationName(item.name)
+        setRelation(item.nameStr)
+        setVisible(false)
+    }
+
+    // 获取亲属关系
+    const GetRelation = async () : Promise<void> => {
+        const data = await getRelation()
+        setRelationList(data)
+    }
+
+
+
+    // 打开不同形式的弹窗
+    const openModal = (value: number) => {
+        setVisible(true)
+        setItemType(value)
+    }
+
+    // 关闭弹窗
+    const closeModal = () => setVisible(false)
+
+    // 保存宝贝信息
+    const PostBaby = async () => {
+        const $par = {
+            birthday,
+            gender,
+            img,
+            name,
+            relationName,
+            relation
+        }
+        Tip.loading('保存宝贝信息中')
+        const data = await postBaby($par)
+        console.log(data);
+        Tip.loaded()
+        Taro.redirectTo({
+             url: '/pages/AuthResult/index'
+        });
+    }
+
+    useEffect( () => {
+        if (itemType === 2 && relationList.length === 0) {
+            GetRelation()
+        }
+    }, [itemType, relationList.length])
+
+
+    const RenderPop = () => {
+        switch (itemType) {
+            case 0:
+                return (
+                    <AtActionSheet isOpened={visible} onClose={closeModal}>
+                        <AtActionSheetItem onClick={() => changeGender(1)}>
+                            男   
+                        </AtActionSheetItem>
+                        <AtActionSheetItem onClick={() => changeGender(2)}>
+                            女
+                        </AtActionSheetItem>
+                    </AtActionSheet>
+                )
+            case 2:
+                return (
+                    <AtFloatLayout isOpened={visible} customStyle={{height: 300}} onClose={closeModal}>
+                        <View className='relation'>
+                            {
+                                relationList?.map( item => (
+                                    <AtActionSheetItem 
+                                      className='sheetItem' 
+                                      key={item.nameStr}
+                                      onClick={() => changeRelation(item)}
+                                    >
+                                        {item.name}
+                                    </AtActionSheetItem>
+                                ))
+                            }
+                        </View>
+                    </AtFloatLayout>
+                )
+        }
+    }
+
+    return (
+        <View className='AddBaby'>
+            <View className='form'>
+                <View className='item ava' style={{height: 90, border: 'none'}}>
+                    <View className='label'>
+                        宝宝头像
+                    </View>
+                    <View className='content'>
+                        {
+                            img ? 
+                            <Image mode='aspectFill' className='ava-img' src={img} onClick={changeAva}></Image> 
+                            : 
+                            <View className='ava-img' onClick={changeAva}></View>
+                        }
+                        
+                        
+                    </View>
+                </View>
+                <View className='item'>
+                    <View className='label'>
+                        昵称
+                    </View>
+                    <View className='content'>
+                        <AtInput 
+                          className='name'
+                          name='name'
+                          placeholderClass='placeholderClass'
+                          placeholder='请输入'
+                          value={name}
+                          onChange={changeName}
+                        />
+                        <Image style={{width: 8, height: 11}} src={require('../../assets/AddBaby/arrow.png')} />
+                    </View>
+                </View>
+                <View className='item' onClick={() => openModal(0)}>
+                    <View className='label'>
+                        性别
+                    </View>
+                    <View className='content'>
+                        <View className='text'>
+                            {switchGender(gender)}
+                        </View>
+                        <Image style={{width: 8, height: 11}} src={require('../../assets/AddBaby/arrow.png')} />
+                    </View>
+                </View>
+                <Picker mode='date' onChange={changeBirthday} value='2'>
+                    <View className='item' onClick={() => openModal(1)}>
+                            <View className='label'>
+                                生日
+                            </View>
+                            <View className='content'>
+                                <View className='text'>{birthday}</View>
+                                <Image style={{width: 8, height: 11}} src={require('../../assets/AddBaby/arrow.png')} />
+                            </View>
+                        </View>
+                </Picker>
+                <View className='item' onClick={() => openModal(2)}>
+                    <View className='label'>
+                        我是宝宝的
+                    </View>
+                    <View className='content'>
+                        <View className='text'>{relationName}</View>
+                        <Image style={{width: 8, height: 11}} src={require('../../assets/AddBaby/arrow.png')} />
+                    </View>
+                </View>
+            </View>
+            
+            <View className='button' onClick={PostBaby}>
+                保存
+            </View>
+
+            {RenderPop()}
+
+        </View>
+    )
+}
+
+export default AddBaby

+ 3 - 0
src/pages/AuthOpra/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '品牌认证查询'
+}

+ 92 - 0
src/pages/AuthOpra/index.scss

@@ -0,0 +1,92 @@
+@import "~taro-ui/dist/style/components/input.scss";
+@import "~taro-ui/dist/style/components/icon.scss";
+@import "~taro-ui/dist/style/components/action-sheet.scss";
+   .AuthOpra-bg {
+        width: 100vw;
+        height: 362px;
+    }
+.renderInputArea {
+    width: 686px;
+    height: 343px;
+    padding: 48px 48px 68px 46px;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    box-shadow: 0px 12px 22px 0px rgba(175, 207, 220, 0.24);
+    border-radius: 20px;
+    position: relative;
+    z-index: 1;
+    margin: 0 auto;
+    margin-top: -48px;
+ 
+    .Atinput {
+        width: 592px;
+        height: 90px;
+        background: #F4F4F4;
+        border-radius: 45px;
+        border: none;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+    .at-input  {
+        padding: 0;
+        border: none;
+        margin-left: 0;
+    }
+    .at-input::after {
+        border: none;
+    }
+    .at-input__input {
+        width: 300px;
+    }
+}
+
+.button {
+    width: 592px;
+    height: 88px;
+    background: #002F95;
+    box-shadow: 0px 4px 20px 0px rgba(0, 47, 149, 0.52);
+    border-radius: 200px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 32px;
+    font-family: PingFangSC-Medium, PingFang SC;
+    font-weight: 500;
+    color: #FFFFFF;
+    margin-top: 40px;
+}
+
+
+.select {
+    width: 592px;
+    height: 90px;
+    border-radius: 45px;
+    border: 1px solid rgba(151, 151, 151, 0.6);
+    margin-bottom: 28px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 28px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #666666;
+}
+
+.scan-button {
+    width: 592px;
+    height: 88px;
+    border-radius: 200px;
+    border: 2px solid #002F95;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin: 0 auto;
+    margin-top: 100px;
+    Text {
+        font-size: 32px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #002F95;
+    }
+}

+ 149 - 0
src/pages/AuthOpra/index.tsx

@@ -0,0 +1,149 @@
+import React, { useEffect, useState } from 'react'
+
+import { View, Image, Text } from '@tarojs/components'
+import { AtInput, AtIcon, AtActionSheet, AtActionSheetItem   } from 'taro-ui'
+import Taro from '@tarojs/taro';
+import './index.scss'
+
+import { queryCertificate, queryCertificateFile } from '../../api/auth'
+
+const SheetItem = [
+    {
+        typeId: 2,
+        label: '逻辑狗思维体验Plus'
+    },
+    {
+        typeId: 3,
+        label: '逻辑狗思维体验Home'
+    },
+    {
+        typeId: 4,
+        label: '逻辑狗思维体验Town'
+    },
+]
+
+const AuthOpra: React.FC = (props) => {
+
+    const [type, setType] = useState<number>(0)
+    
+    const [label, setLabel] = useState<string>('')
+
+
+    // 弹窗
+    const [visible, setVisible] = useState<boolean>(false)
+
+    const onChange = (e: React.SetStateAction<string> ) => setLabel(e)
+
+    // 查询证书
+    const QueryCertificate = async (): Promise<void> => {
+        Taro.navigateTo({
+             url: '/pages/AuthResult/index'
+        });
+    //   const data = await queryCertificate({label, typeId: type})
+      
+    //   console.log(data);
+      
+    }  
+
+    // 上传证书url
+    const QueryCertificateFile = async (fileUrl: string, typeId: number): Promise<void> => {
+        const data = await queryCertificateFile({fileUrl, typeId})
+        console.log(data);
+    }
+
+    // 调起微信的拍照或者相册选择证书
+    const dispatchWxCamera = () => {
+        Taro.chooseImage({
+            success: res => {
+                const tempFilePaths = res.tempFilePaths
+                Taro.uploadFile({
+                    url: 'http://training.luojigou.vip/training/file/uploadFile',
+                    filePath: tempFilePaths[0],
+                    name: 'file',
+                    header: {
+                        token: Taro.getStorageSync('token')
+                    },
+                    formData: {
+                        'user': 'test'
+                    },
+                    success: (uploadFileRes) => {
+                        QueryCertificateFile(uploadFileRes.data, type)
+                    }
+                });
+            }
+        })
+    }  
+
+
+    
+    useEffect( () => {
+
+        setType(Number(Taro.getCurrentInstance().router?.params.type))
+
+    }, []) 
+
+    
+
+    // 渲染输入框
+    const renderInputArea = () => {
+        return (
+            <View className='renderInputArea'>
+                {
+                    type === 1 && 
+                    <View className='select' onClick={() => setVisible(true)}>
+                        <View >
+                            <Text>请选择逻辑狗思维体验馆</Text>
+                            {/* <AtIcon value='play' size='30' customStyle={{color: '#000'}}></AtIcon> */}
+                        </View>
+                    </View>
+                }
+                <AtInput
+                  name='value'
+                  value={label}
+                  onChange={onChange}
+                  className='Atinput'
+                  placeholderStyle='color: #666666;'
+                  placeholder='请输入门店名称/证书编号'
+                />
+
+                <View className='button' onClick={QueryCertificate}>
+                    立即查询
+                </View>
+
+                <AtActionSheet isOpened={visible}>
+                    {
+                        SheetItem.map( item => (
+                            <AtActionSheetItem key={item.typeId}>
+                                {item.label}
+                            </AtActionSheetItem>
+                        ))
+                    }
+                  
+                </AtActionSheet>
+            </View>
+        )
+    }
+
+    return (
+        <View className='AuthOpra'>
+            <Image
+              mode='aspectFill'
+              className='AuthOpra-bg'
+              src={require(`../../assets/authOpra/type${type}.png`)}
+            />
+            { renderInputArea()}
+
+            {/* 扫描 */}
+
+            <View className='scan-button' onClick={dispatchWxCamera}>
+                <View>
+                    <Image style={{width: 15, height: 15, marginRight: 13, display: 'block'}} src={require('../../assets/authOpra/scan-icon.png')}></Image>
+                </View>
+                <Text >扫描</Text>    
+            </View>
+
+        </View>
+    )
+}
+export default AuthOpra
+

+ 4 - 0
src/pages/AuthQuery/index.config.ts

@@ -0,0 +1,4 @@
+export default {
+    navigationStyle: 'custom'
+}
+  

+ 30 - 0
src/pages/AuthQuery/index.scss

@@ -0,0 +1,30 @@
+@import "~taro-ui/dist/style/components/grid.scss";
+
+
+.AuthQuery {
+    .AuthQuery-img {
+        width: 100vw;
+        height: 376px;
+    }
+    .step {
+        width: 730px;
+        height: 288px;
+        margin: 0 10px;
+        margin-top: -140px;
+        
+    }
+}
+
+.CateGrid {
+    padding: 0 32px;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.gridImg {
+    width: 336px;
+    height: 220px;
+    margin-bottom: 80px;
+}

+ 54 - 0
src/pages/AuthQuery/index.tsx

@@ -0,0 +1,54 @@
+import React from 'react'
+
+import { AtGrid } from "taro-ui"
+import { Image, View } from '@tarojs/components' 
+
+import Taro from '@tarojs/taro'
+
+import './index.scss'
+
+import bg from '../../assets/authQuery/auth-bg.png'
+import step from '../../assets/authQuery/three-step.png'
+
+console.log(bg);
+
+
+const gridList = new Array(5).fill(0)
+
+const CateGrid: React.FC = () => {
+
+    const goPage = (index: number): void => {
+        Taro.navigateTo({
+             url: `/pages/AuthOpra/index?type=${index}`
+        });
+    }
+
+    return (
+        <View className='CateGrid'>
+            { 
+                gridList.map((item, index) => (
+                    <Image 
+                      key={item} 
+                      className='gridImg' 
+                      src={require(`../../assets/authQuery/auth${index}.png`)}
+                      onClick={() => goPage(index)}
+                    />
+                ))
+            }
+        </View>
+    )
+} 
+
+
+const AuthQuery: React.FC = () => {
+    return (
+        <View className='AuthQuery'>
+            <Image className='AuthQuery-img' src={bg} />
+            <Image className='step'  src={step} mode='aspectFill' />
+            <CateGrid />
+        </View>
+        // <image src='https://img12.360buyimg.com/jdphoto/s72x72_jfs/t6160/14/2008729947/2754/7d512a86/595c3aeeNa89ddf71.png' ></image>
+    )
+}
+
+export default AuthQuery

+ 3 - 0
src/pages/AuthResult/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationStyle: 'custom'
+}

+ 113 - 0
src/pages/AuthResult/index.scss

@@ -0,0 +1,113 @@
+.AuthResult {
+    width: 100vw;
+    min-height: 100vh;
+    background: #FFFFFF;
+    .bg {
+        width: 100vw;
+        height: 376px;    
+    }   
+}
+
+
+.company {
+    width: 686px;
+    height: 726px;
+    background: #FFFFFF;
+    box-shadow: 0px 12px 22px 0px rgba(175, 207, 220, 0.24);
+    border-radius: 20px;
+    margin: 0 auto;
+    margin-top: -118px;
+    position: relative;
+    z-index: 1;
+
+    .header {
+        font-size: 28px;
+        font-family: PingFangSC-Semibold, PingFang SC;
+        font-weight: 600;
+        color: #666666;
+        height: 108px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+    .line {
+        width: 626px;
+        height: 2px;
+        background-color: #EBEBEB;
+        margin: 0 auto;
+    }
+
+    .company-name {
+        width: 100%;
+        font-size: 40px;
+        font-family: PingFangSC-Semibold, PingFang SC;
+        font-weight: 600;
+        color: #002F95;
+        text-align: center;
+        margin-top: 38px;
+    }
+    .company-desc {
+        font-size: 28px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #999999;
+        margin-top: 16px;
+        margin-bottom: 40px;
+        text-align: center;
+    }
+
+    .certificate {
+        width: 100%;
+        height: 444px;
+        position: relative;
+        .business-license {
+            width: 258px;
+            height: 362px;
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            z-index: 2;
+        }
+        .chapter {
+            width: 211px;
+            height: 228px;
+            position: absolute;
+            right: 60px;
+            bottom: 60px;
+            z-index: 3;
+        }
+    }
+}
+
+// 最下边的证书
+.chapter {
+    width: 686px;
+    margin: 0 auto;
+    margin-top: 56px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    .header {
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        .dog {
+            width: 90px;
+            height: 102px;
+        }
+        Text {
+            font-size: 32px;
+            font-family: PingFangSC-Semibold, PingFang SC;
+            font-weight: 600;
+            color: #161616;
+        }
+    }
+    .chapter-img {
+        width: 614px;
+        height: 428px;
+        
+        margin-top: 22px;
+    
+    }
+}

+ 44 - 0
src/pages/AuthResult/index.tsx

@@ -0,0 +1,44 @@
+import React from 'react'
+
+import { View, Image, Text } from '@tarojs/components'
+
+import './index.scss'
+
+const AuthResult: React.FC = () => {
+    
+    return (
+        <View className='AuthResult'>
+            <Image className='bg' src={require('../../assets/AuthResult/bg.png')} />
+
+            {/* 合作商卡片 */}
+            <View className='company'>
+                <View className='header'>
+                    已通过中德智慧官方认证合作商
+                </View>
+                <View className='line'></View>
+
+                <View className='company-name'>
+                    上海金桥国际龙有限公司
+                </View>
+                <View className='company-desc'>
+                    上海金桥国际龙有限公司
+                </View>
+                <View className='certificate'>
+                    <Image className='business-license' src={require('../../assets/AuthResult/book1.png')} />
+                    <Image className='chapter' src={require('../../assets/AuthResult/chapter.png')} />
+                </View>
+            </View>
+
+            {/* 证书 */}
+            <View className='chapter'>
+                <View className='header'>
+                    <Image className='dog' src={require('../../assets/AuthResult/dog.png')} />
+                    <Text>中德智慧教育官方授权品牌认证证书</Text>
+                </View>
+                <Image className='chapter-img' src={require('../../assets/AuthResult/book.png')} />
+            </View>
+        </View>
+    )
+}
+
+export default AuthResult

+ 3 - 0
src/pages/QueryRecord/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '查询真伪记录'
+}

+ 64 - 0
src/pages/QueryRecord/index.scss

@@ -0,0 +1,64 @@
+.QueryRecord {
+    width: 100vw;
+    min-height: 100vh;
+    background: #F9F9F9;
+    overflow: hidden;
+    padding-bottom: 20px;
+}
+
+.QueryRecord-item {
+    width: 686px;
+    height: 200px;
+    background: #FFFFFF;
+    box-shadow: 0px 4px 8px 0px rgba(220, 220, 220, 0.5);
+    border-radius: 20px;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    margin: 0 auto;
+    margin-top: 40px;
+    padding-left: 32px;
+    box-sizing: border-box;
+    Image {
+        width: 204px;
+        height: 136px;
+    }
+
+    .shop-info {
+        flex: 1;
+        margin-left: 35px;
+        .shop-version {
+            font-size: 32px;
+            font-family: PingFangSC-Medium, PingFang SC;
+            font-weight: 500;
+            color: #161616;
+        }
+        .shop-cate {
+            font-size: 24px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #666666;
+        }
+    }
+
+    .button {
+        margin-right: 38px;
+        width: 124px;
+        height: 60px;
+        border-radius: 44px;
+        background: #F3F3F3;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 24px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #999999;
+    }
+
+    .unclaimed {
+        color: #FFFFFF;
+        background: #002F95;
+        box-shadow: 0px 4px 20px 0px rgba(0, 47, 149, 0.52);
+    }
+}

+ 85 - 0
src/pages/QueryRecord/index.tsx

@@ -0,0 +1,85 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+import React, { useEffect, useState } from 'react'
+
+import { View, Image } from '@tarojs/components'
+
+import Taro from '@tarojs/taro'
+
+import './index.scss'
+
+import { getRecord } from '../../api/qrcode'
+
+import Tip from '../../utils/tip'
+
+type recordsListType = {
+    id: string,
+    imgUrl: string,
+    hasGot: number,
+    name: string,
+    [key: string]: any
+}
+
+const QueryRecord: React.FC = () => {
+
+    const [page , setPage] = useState<number>(1)
+
+    const [recordsList, setRecordsList] = useState<recordsListType[]>([])
+
+    // 请求一次之后, 如果记录已经全部请求到了, 将不会再次请求, 不会再次请求
+    const [stopRequest, setStopRequest] = useState<boolean>(false)
+
+    // 获取查询记录
+
+    const GetRecord = async (): Promise<void> => {
+
+        Tip.loading('努力加载记录中~')
+
+        const data = await getRecord({page})
+        
+        Tip.loaded()
+
+        // 当当前返回数组为空时
+        if(data.entityList.length === 0) {
+            Tip.toast('没有更多记录了')
+            setStopRequest(true)
+            return 
+        }
+
+        const oldRecords = [...recordsList]
+        const newRecords = oldRecords.concat(...data.entityList)
+        setRecordsList(newRecords)
+    }
+
+    Taro.useReachBottom(() => setPage(page + 1))
+
+    useEffect( () => {
+        if(stopRequest) return
+        GetRecord()
+    }, [ page])
+
+    return (
+        <View className='QueryRecord'>
+            {
+                recordsList?.map(item => (
+                    <View className='QueryRecord-item' key={item.id}>
+                        <Image src={item.imgUrl} mode='aspectFill' />
+                        <View className='shop-info'>
+                            <View className='shop-version'>
+                                {item.name}
+                            </View>
+                            <View className='shop-cate'>
+                                3-4岁第一阶段
+                            </View>
+                        </View>
+
+                        <View className='button'>
+                            未领取
+                        </View>
+                    </View>
+                ))
+            }
+        </View>
+    )
+}
+
+export default QueryRecord

+ 19 - 0
src/pages/ScanQrcode/data.d.ts

@@ -0,0 +1,19 @@
+
+export type modalProps = {
+    visable: boolean,
+    closeModal: () => void,
+    errorCode: authQrcodeType["errorCode"]
+}
+
+/**
+ * @param {number} errorCode  -1 正常 0 码错误 1 已被扫
+ * @param {number} goodsParentType  0 网络版 1 家庭版 2 教学版 3 聪明书
+ * @param {number} isNewCode  0 旧版 1 新码
+ * 
+ */
+
+export type authQrcodeType = {
+    errorCode: 0 | -1 | 1,
+    goodsParentType: 0 | 1 | 2 | 3,
+    isNewCode: 0 | 1
+}

+ 3 - 0
src/pages/ScanQrcode/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '查询真伪',
+}

+ 179 - 0
src/pages/ScanQrcode/index.scss

@@ -0,0 +1,179 @@
+@import "~taro-ui/dist/style/components/input.scss";
+@import "~taro-ui/dist/style/components/curtain.scss";
+.ScanQrcode {
+    width: 100vw;
+    height: 100vh;
+    background: #F9F9F9;
+    padding: 0 24px;
+    overflow: hidden;
+    box-sizing: border-box;
+}
+
+.header {
+    margin-top: 42px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .left {
+        font-size: 44px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #161616;
+    }
+    .right {
+        font-size: 28px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #002F95;
+    }
+}
+
+.Atinput-box {
+    width: 702px;
+    height: 114px;
+    background: #FFFFFF;
+    box-shadow: 0px 4px 20px 0px rgba(208, 208, 208, 0.18);
+    border-radius: 16px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 32px 48px;
+    box-sizing: border-box;
+    margin: 66px 0;
+    .placeholder-class {
+        color: #666666;
+        font-size: 28px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+    }
+    .Atinput {
+        flex: 1;
+    }
+    .scan-icon {
+        width: 40px;
+        height: 40px;
+    }
+}
+
+.at-input::after {
+    border: none;
+}
+
+.at-input  {
+    padding: 0;
+    border: none;
+    margin-left: 0;
+}
+
+
+
+.query-btn {
+    width: 674px;
+    height: 96px;
+    background: #002F95;
+    box-shadow: 0px 4px 20px 0px rgba(0, 47, 149, 0.52);
+    border-radius: 176px;
+    margin: 0 auto;
+    font-size: 32px;
+    font-family: PingFangSC-Medium, PingFang SC;
+    font-weight: 500;
+    color: #FFFFFF;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+
+.verify {
+    margin-top: 134px;
+    .header {
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        margin-bottom: 58px;
+        .flag {
+            width: 6px;
+            height: 28px;
+            background: #23D321;
+            border-radius: 200px;
+            margin-right: 8px;
+        }
+        Text {
+            font-size: 32px;
+            font-family: PingFangSC-Semibold, PingFang SC;
+            font-weight: 600;
+            color: #333333;
+        }
+    }
+
+    .content {
+        width: 702px;
+        height: 426px;
+        background: #FFFFFF;
+        box-shadow: 0px 4px 20px 0px rgba(208, 208, 208, 0.18);
+        border-radius: 16px;
+        padding: 8px 16px ;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        box-sizing: border-box;
+        .shop {
+            width: 350px;
+            height: 406px;
+        }
+        .text {
+            width: 294px;
+            height: 168px;
+            font-size: 28px;
+            color: #333;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            Text {
+                font-size: 32px;
+                color: #002F95;
+                font-weight: bold;
+            }
+        }
+    }
+}
+
+
+// 弹窗
+
+.at-curtain__container {
+
+    width: 100%;
+}
+
+
+.card {
+    width: 674px;
+    height: 588px;
+    background: #FFFFFF;
+    box-shadow: 0px 8px 12px 0px rgba(201, 186, 186, 0.17);
+    border-radius: 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    align-items: center;
+    margin: 0 auto;
+    Image {
+
+    }
+    .label {
+        font-size: 36px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #161616;
+        margin-top: 34px;
+        margin-bottom: 6px;
+        text-align: center;
+    }
+    .desc {
+        font-size: 28px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #666666;
+    }
+}

+ 176 - 0
src/pages/ScanQrcode/index.tsx

@@ -0,0 +1,176 @@
+import React, { useState, useEffect, useCallback } from 'react'
+import { View, Text, Image, Icon } from '@tarojs/components'
+import { AtInput, AtCurtain } from 'taro-ui'
+
+import Taro from '@tarojs/taro'
+import './index.scss'
+
+
+
+import type { modalProps, authQrcodeType } from './data'
+
+import { authQrcode } from '../../api/qrcode'
+import Tip from '@/utils/tip'
+
+const Modal: React.FC<modalProps> = ({visable, closeModal, errorCode}) => {
+
+    const RenderImage = (): React.ReactNode => {
+        switch (errorCode) {
+            case 1:
+                return (
+                    <View>
+                        <Image
+                          style={{width: 143, height: 103}}
+                          src={require('../../assets/ScanQrcode/hava-already.png')}
+                        />
+                        <View >
+                            <View className='label'>条形码已经被使用</View>
+                            <View className='desc' >您可在查询记录里查看~</View>
+                        </View>
+                    </View>
+                )
+        
+            case 0:
+                return (
+                    <View>
+                        <Image
+                          style={{width: 143, height: 103}}
+                          src={require('../../assets/ScanQrcode/query-faild.png')}
+                        />
+                        <View>
+                            <View className='label'>商品查询失败</View>
+                            <View className='desc' >请填写正确的数字条形码~</View>
+                        </View>
+                    </View>
+                    
+                )
+        }
+    }
+
+
+    return (
+        <AtCurtain
+          isOpened={visable}
+          onClose={closeModal}
+        >
+        <View className='card'>
+            { RenderImage() }
+        </View>
+        
+      </AtCurtain>
+    )
+}
+
+
+const ScanQrcode: React.FC = () => {
+
+    const [ visable, setVisable ] = useState<boolean>(false)
+
+    const [ code, setCode] = useState<string>('')
+
+    const [ errorCode, setErrorCode ]  = useState<-1 | 0 | 1>(0)
+
+    const [ qrcode, setQrcode ] = useState<string>('')
+
+    // 输入二维码
+    const onChange = (e: string): void => setCode(e)
+
+    // 打开弹窗
+    const openModal = (): void => setVisable(true)
+
+    // 关闭
+    const closeModal = (): void => setVisable(false)
+ 
+    // 打开摄像头扫码
+    const scanQrcode = (): void => {
+        setCode('')
+        Taro.scanCode({
+            success: res => {
+                console.log(res);
+                const { rawData } = res
+                AuthQrcode(rawData)
+            },
+            fail: () => {
+                Tip.toast('图片不是条形码或者二维码',  'none', 3000 )
+            }
+        })
+    } 
+
+    // 查询二维码
+    const AuthQrcode = useCallback(async (params: string = ''): Promise<void> => {
+
+        Taro.setStorageSync('goodsTypePdfId',  params || code)
+        
+        const data = await authQrcode(params || code)
+
+        const {errorCode: ErrorCode, goodsParentType, isNewCode } = data as unknown as authQrcodeType
+        setErrorCode(ErrorCode)
+
+        if (isNewCode === 0 ) {  // 旧码
+
+            Taro.navigateTo({
+                 url: '/pages/ShopCate/index'
+            });
+
+            return 
+        } 
+
+        if (errorCode !== -1) {
+            openModal()
+        }
+    }, [code, errorCode])
+
+
+    // 去查询详情页
+    const goPage = (): void => {
+        Taro.navigateTo({
+             url: '/pages/QueryRecord/index'
+        });
+    }
+
+    return (
+        <View className='ScanQrcode'>
+            <View className='header'>
+                <Text className='left'>输入/扫描数字条形码 </Text>
+                <Text className='right' onClick={goPage}>查询记录</Text>
+            </View>
+            <View className='Atinput-box'>
+                <AtInput 
+                  name='qrcode' 
+                  className='Atinput'
+                  onChange={onChange}
+                  value={code}
+                  placeholder='请输入数字条形码'
+                  placeholderStyle='placeholder-class'
+                />
+                <Image className='scan-icon' onClick={scanQrcode} src={require('../../assets/ScanQrcode/scan-icon.png')}></Image>
+            </View>
+            <View className='query-btn' onClick={() => AuthQrcode()}>立即查询</View>
+
+            {/* 验证方法 */}
+
+            <View className='verify'>
+                <View className='header'> 
+                    <View className='flag'></View>
+                    <Text>验证方法</Text>
+                </View>
+                <View className='content'>
+                    <Image
+                      mode='aspectFill'
+                      className='shop' 
+                      src={require('../../assets/ScanQrcode/shop.png')}
+                    />
+                    <View className='text'>
+                        通过手机扫一扫盒子
+                        <Text>左侧条形码</Text>
+                        或者输入
+                        <Text>条形码下方数字</Text>
+                        ,即 可进行真伪验证
+                    </View>
+                </View>
+            </View>
+            <Modal  visable={visable} closeModal={closeModal} errorCode={errorCode} />
+        </View>
+    )
+}
+export default ScanQrcode

+ 12 - 0
src/pages/ScanResult/data.d.ts

@@ -0,0 +1,12 @@
+export type itemListType = {
+    label: string,
+    desc: string,
+    clickText: string,
+}
+
+
+export type RenderAtFloatLayoutRrops = {
+    visible: boolean,
+    closePop: () => void,
+    openCurtainModal: () => void
+}

+ 3 - 0
src/pages/ScanResult/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '查询结果'
+}

+ 215 - 0
src/pages/ScanResult/index.scss

@@ -0,0 +1,215 @@
+@import "~taro-ui/dist/style/components/float-layout.scss";
+@import "~taro-ui/dist/style/components/icon.scss";
+@import "~taro-ui/dist/style/components/curtain.scss";
+.ScanResult {
+    width: 100vw;
+    height: 100vh;
+    background: #F9F7F7;
+    padding: 18px 24px;
+    box-sizing: border-box;
+}
+
+
+// 背景图
+.result-bg {
+    width: 702px;
+    height: 304px;
+    position: relative;
+    margin-bottom: 80px;
+    Image {
+        width: 702px;
+        height: 304px;
+    }
+    .result-text {
+        position: absolute;
+        top: 46px;
+        left: 40px;
+        width: 416px;
+    }
+}
+
+
+.result-bg view:first-child {
+    font-size: 44px;
+    font-family: PingFangSC-Semibold, PingFang SC;
+    font-weight: 600;
+    color: #FFFFFF;
+}
+
+.result-bg view:last-child {
+    font-size: 24px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #FFFFFF;
+}
+
+
+// item区
+.renderItem-box {
+    .item {
+        width: 702px;
+        height: 220px;
+        background: #FFFFFF;
+        box-shadow: 0px 4px 12px 0px rgba(246, 241, 241, 0.64);
+        border-radius: 20px;
+        padding: 26px 38px 24px 26px;
+        box-sizing: border-box;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        margin-top: 22px;
+        Image {
+            width: 170px;
+            height: 170px;
+            display: block;
+        }
+        .text {
+            flex: 1;
+            margin-left: 24px;
+            margin-right: 100px;
+            .label {
+                width: 120%;
+                font-size: 32px;
+                font-family: PingFangSC-Medium, PingFang SC;
+                font-weight: 500;
+                color: #161616;
+            }
+            .desc {
+                font-size: 24px;
+                font-family: PingFangSC-Regular, PingFang SC;
+                font-weight: 400;
+                color: #999999;
+            }
+        }
+        .button {
+            width: 152px;
+            height: 60px;
+            background: #002F95;
+            box-shadow: 0px 4px 8px 0px rgba(0, 47, 149, 0.4);
+            border-radius: 44px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            font-size: 24px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #FFFFFF;
+        }
+    }
+}
+
+
+
+
+// 绑定信息时的弹层
+.AtFloatLayout {
+    .header {
+        width: 686px;
+        margin: 0 auto;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        font-size: 32px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #161616;
+    }
+
+    .title {
+       display: flex;
+       justify-content: center;
+       align-items: center;
+       text-align: center;
+       margin-bottom: 32px;
+       margin-top: 42px;
+        .line {
+            width: 28px;
+            height: 2px;
+            background-color: #999999;
+            margin: 0 26px;
+        }
+        .text {
+            font-size: 32px;
+            font-family: PingFangSC-Medium, PingFang SC;
+            font-weight: 500;
+            color: #161616;
+        }
+    }
+    .desc {
+        font-size: 24px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #C8C8C8;
+    }
+
+    // 孩子信息
+    .children {
+        .children-itme {
+            width: 686px;
+            height: 166px;
+            background: #FFFFFF;
+            border-radius: 20px;
+            border: 2px solid #002F95;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            padding-left: 30px;
+            box-sizing: border-box;
+            margin-top: 22px;
+            Image {
+                width: 100px;
+                height: 100px;
+                border-radius: 50%;
+            }
+            .baby-info {
+                margin-left: 50px;
+                .baby-name {
+                    font-size: 32px;
+                    font-family: PingFangSC-Semibold, PingFang SC;
+                    font-weight: 600;
+                    color: #161616;
+                    margin-bottom: 4px;
+                }
+                .baby-age {
+                    font-size: 28px;
+                    font-family: PingFangSC-Regular, PingFang SC;
+                    font-weight: 400;
+                    color: #999999;
+                }
+            }
+        }
+    }
+
+
+
+    // 添加按钮
+    .add-btn {
+        width: 686px;
+        height: 108px;
+        background: #F6F6F6;
+        border-radius: 170px;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        padding-left: 62px;
+        box-sizing: border-box;
+        margin-top: 42px;
+        .placehoader {
+            font-size: 28px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #666666;
+            margin-left: 40px;
+        }
+    }
+}
+
+
+.AtCurtain {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    .get-success {
+        margin-left: -26px;
+    }
+}

+ 213 - 0
src/pages/ScanResult/index.tsx

@@ -0,0 +1,213 @@
+import React, { useState, useEffect}  from 'react'
+import { View, Text, Image, Button } from '@tarojs/components'
+
+import { AtFloatLayout , AtIcon, AtCurtain } from 'taro-ui'
+
+import Taro from '@tarojs/taro'
+
+import './index.scss'
+
+import type { itemListType, RenderAtFloatLayoutRrops } from './data'
+
+import { getBaby, getManual } from '../../api/user'
+
+const itemList: itemListType[] = [
+    {
+        label: '家长指导手册',
+        desc: '家长指导手册',
+        clickText: '领取礼品'
+    },
+    {
+        label: '逻辑狗老师',
+        desc: '一对一辅导',
+        clickText: '去添加'
+    },
+    // {
+    //     label: '免费家长引导课',
+    //     desc: '抓紧体验吧',
+    //     clickText: '立即体验'
+    // },
+]
+
+// 绑定信息时的弹层
+const RenderAtFloatLayout: React.FC<RenderAtFloatLayoutRrops> = ({
+    visible,
+    closePop,
+    openCurtainModal   
+}) => {
+
+    const [babyList, setBabyList] = useState<Record<string, any>>([])
+
+    // 获取boby信息
+    const GetBaby = async (): Promise<void> => {
+      const data = await getBaby()
+      console.log(data, '获取baby信息');
+      setBabyList(data)
+    }
+
+
+    // 确定领取指导手册
+    const GetManual = async () => {
+      const $par = babyList.map( item => {
+        //   
+          return {
+              id: item.id,
+              goodsTypePdfId: Taro.getStorageSync('goodsTypePdfId')
+          }
+      })
+      const data = await getManual($par)
+      console.log(data);
+      openCurtainModal()
+    }
+
+    useEffect( () => {
+        GetBaby()
+    }, [])
+
+    return (
+        <AtFloatLayout 
+          isOpened={visible}
+          onClose={closePop}
+          className='AtFloatLayout'
+        >
+         <View className='header'>
+            <View onClick={closePop}>取消</View>
+            <View onClick={GetManual}>确定</View>
+         </View>
+         <View className='title'>
+            <View className='line'></View>
+            <Text className='text'>请选择宝宝</Text>
+            <View className='line'></View>
+        </View>
+         <View className='desc'>领取礼品需要填写/选择宝贝信息</View>
+         {/* 孩子信息 */}
+         <View className='children'>
+           {
+               babyList?.map(item => (
+                <View className='children-itme' key={item.id}>
+                    <Image src={item.img} mode='aspectFill' />
+                    <View className='baby-info'>
+                        <View className='baby-name'>{item.name}</View>
+                        <View className='baby-age'>{item.age.replace(/\-/, '')}</View>
+                    </View>
+                </View>
+               ))
+           }
+         </View>
+         {/* 添加按钮 */}
+         <View className='add-btn'>
+            <AtIcon size='23' color='rgb(108, 108, 108)' value='add-circle' />
+            <Text className='placehoader'>添加宝宝信息</Text>
+         </View>
+      </AtFloatLayout>
+    )
+}
+
+
+const ScanResult: React.FC = ({}) => {
+
+    const [ visible, setVisible ] = useState<boolean>(false)
+
+    const [curtainState, setCurtainState] = useState<boolean>(false)
+
+    // 打开幕帘
+    const openCurtainModal = () => setCurtainState(true)
+
+    // 打开弹窗
+    const openPop = (): void => setVisible(true)
+
+    // 关闭弹窗
+    const closePop = (): void => setVisible(false)
+
+    // 渲染登录按钮
+    const RenderButton =  (item: itemListType, index: number) => {
+        
+
+
+        // 打开客服会话 
+
+        const handleContact = (e) => {
+            console.log(e);
+        }
+
+        switch (index) {
+            case 0:
+                return  (
+                    <Button className='button' onClick={openPop}  >
+                        {item.clickText}
+                    </Button>
+                )
+            case 1:
+                
+                return (
+                    <Button className='button' openType='contact' onContact={handleContact} >
+                        {item.clickText}
+                    </Button>
+                )
+        }
+    }
+
+    // 渲染领取的指导手册
+    const RenderItem = ()  => {
+
+        return (
+            <View className='renderItem-box'>
+                {
+                    itemList.map( (item, index) => (
+                        <View className='item' key={item.label}>
+                            <Image src={require(`../../assets/ScanResult/result${index}.png`)} />
+                            <View className='text'>
+                                <View className='label'>{item.label}</View>
+                                <View className='desc'>{item.desc}</View>
+                            </View>
+                            {/* buttong */}
+                            {
+                                RenderButton(item, index)
+                            }
+                        </View>
+                    ))
+                }
+                
+            </View>
+        )
+    }
+
+    return (
+        <View className='ScanResult'>
+            <View className='result-bg'>
+                <Image
+                  onClick={openPop}
+                  src={require('../../assets/ScanResult/reuslt-bg.png')}
+                  mode='aspectFit'
+                />
+                <View className='result-text'>
+                    <View> 逻辑狗正版验证通过!</View>
+                  
+                    <View> 北京市中德智慧教育文化有限公司 </View>
+                </View>
+            </View>
+            {/* 渲染物品领取页 */}
+            { RenderItem() }
+
+
+            {/* 绑定信息的弹层 */}
+            <RenderAtFloatLayout visible={visible} closePop={closePop} openCurtainModal={openCurtainModal} />
+
+            {/* 领取成功弹层 */}
+            <AtCurtain
+              isOpened={curtainState}
+              onClose={() => setCurtainState(false)}
+              className='AtCurtain'
+            >
+                <Image 
+                  mode='aspectFill'
+                  className='get-success'
+                  style='width: 349px;height: 408px'
+                  src={require('../../assets/ScanResult/getSuccess.png')}
+                />
+        </AtCurtain>
+        </View>
+    )
+}
+
+export default ScanResult

+ 3 - 0
src/pages/ShopCate/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+    navigationBarTitleText: '请选择您想要查询的商品'
+}

+ 35 - 0
src/pages/ShopCate/index.scss

@@ -0,0 +1,35 @@
+.ShopCate {
+    width: 100vw;
+    min-height: 100vh;
+    background: #F9F7F7;
+    overflow: hidden;
+    padding-bottom: 20px;
+}
+
+.ShopCate-item {
+    width: 686px;
+    height: 200px;
+    background: #FFFFFF;
+    box-shadow: 0px 4px 12px 0px rgba(246, 241, 241, 0.64);
+    border-radius: 20px;
+    margin: 0 auto;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    padding-left: 70px;
+    box-sizing: border-box;
+    margin-top: 40px;
+    Image {
+        width: 126px;
+        height: 84px;
+    }
+    .cate-name {
+        font-size: 32px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #161616;
+        margin-left: 76px;
+    }
+}
+
+

+ 62 - 0
src/pages/ShopCate/index.tsx

@@ -0,0 +1,62 @@
+import React, { useState, useEffect, useCallback } from 'react'
+
+import { View, Image } from '@tarojs/components'
+
+import Taro from '@tarojs/taro'
+
+import {  getGoodsList } from '../../api/qrcode'
+
+import Tip from '../../utils/tip'
+
+import './index.scss'
+
+type shopListType = {
+    [key: string]: any
+}
+
+const ShopCate: React.FC = () => {
+
+    const [shopList, setShopList] = useState<shopListType[]>([])
+
+    // 跳转页面
+
+    const goPage = (): void => {
+        Taro.navigateTo({
+             url: '/pages/ScanResult/index'
+        });
+    }
+
+
+    // 获取商品
+
+    const GetGoodsList = useCallback(async (): Promise<void> => {
+
+        Tip.loading('努力加载中~')
+
+        const data = await getGoodsList()
+
+        Tip.loaded()
+
+        setShopList(data as shopListType[])
+    }, [])
+
+    useEffect( () => {
+        GetGoodsList()
+    }, [GetGoodsList])
+
+
+    return (
+        <View className='ShopCate'>
+                {
+                    shopList?.map(item => (
+                        <View className='ShopCate-item' key={item.id} onClick={goPage}>
+                            <Image src={item.imgUrl} />
+                            <View className='cate-name'>{item.name}</View>
+                        </View>
+                    ))
+                }
+        </View>
+    )
+}
+
+export default ShopCate

+ 8 - 0
src/pages/home/index.scss

@@ -0,0 +1,8 @@
+@import "~taro-ui/dist/style/components/input.scss";
+.card {
+    width: 730px;
+    height: 180px;
+    border-radius: 20px;
+    margin: 0 auto;
+    background-color: #e8e8e8;
+}

+ 142 - 4
src/pages/home/index.tsx

@@ -1,8 +1,146 @@
-import React from 'react'
+import React, { Component, useState, memo, useEffect, useMemo, useCallback } from 'react'
+import { View } from '@tarojs/components'
+import { AtInput } from 'taro-ui'
+import { produce } from 'immer'
 
-const Home: React.FC = () => {
+import './index.scss'
+
+
+
+const Caaaa = memo( (props) => {
+    console.log('render...');
+    
+    return <AtInput name='text' value={props.val} onChange={props.onChange} />;
+} );
+  
+const App = () => {
+    const [val1, setVal1] = useState('1');
+    const [val2, setVal2] = useState('2');
+  
+    const onChange1 = useCallback( evt => {
+        console.log('onChange1');
+        
+        // console.log(evt, 'evt');
+        
+    //   setVal1(evt.target.value);
+    }, []);
+  
+    const onChange2 = useCallback( evt => {
+        console.log(evt);
+    //   setVal2(evt.target.value);
+    }, []);
+  
+    return (
+        <View>
+            <Caaaa val={val1} onChange={onChange1} ></Caaaa>
+            <Caaaa val={val2} onChange={onChange2} ></Caaaa>
+        </View>
+    );
+  }
+
+
+const Card = memo(({name}) => {
+  
+    console.log('Card函数执行');
+    
+    const stopMulRender = HTMLElement => {
+        console.log('stopMulRender函数执行');
+        
+        return HTMLElement
+    }
+
+    // const memoValue = useMemo(() => stopMulRender(name), [name])
+
+    const callbackValue = useCallback( () => {
+        console.log('我执行了么');
+        
+        stopMulRender(name)
+    }, [name])
+
+    console.log(callbackValue, 'memoValue');
+    
+    const log  = () => {
+        console.log('log被打印');
+        
+    }
     return (
-        <text>2</text>
+        <View className='card'>
+            {log()}
+            {name}
+        </View>
     )
+})
+
+// const App = () => {
+//     const [name, setName] = useState('名称')
+//     const [content,setContent] = useState('内容')
+//     return (
+//         <View>
+//           <View onClick={() => setName(new Date().getTime())}>name</View>
+//           <View onClick={() => setContent(new Date().getTime())}>content</View>
+//           {/* {content} */} 
+//           <Card name={name}></Card>
+//         </View>
+//     )
+//   }
+
+
+class Home extends Component {
+
+
+
+
+   constructor (props) {
+        super(props)
+        this.state = {
+            count: 1,
+            like: true
+        }
+   }
+
+   componentDidMount () {
+        this.setState((state) => {
+            return {
+                count: state.count + 3
+            }
+        })
+        this.setState((state) => {
+            return {
+                count: state.count + 10
+            }
+        },  () => {
+            console.log(this.state);
+        })
+   }
+
+    Hello () { 
+        return <View>Hello2222</View>
+    }
+
+
+    handleCount = () => {
+        this.setState({
+            count: 10000
+        }, () => {
+            console.log(this.state.count);
+            
+        })
+    }
+    
+
+    render () {
+
+        
+        return (
+            <View>
+                <View onClick={this.handleCount}>click me</View>
+                <Card like={this.state.like}>
+                    {/* <View>hello</View>
+                    <View>ccc</View> */}
+                </Card>
+            </View>
+        )
+    }
 }
-export default Home
+
+export default App

+ 35 - 1
src/pages/index/index.scss

@@ -1,2 +1,36 @@
 @import "~taro-ui/dist/style/components/nav-bar.scss";
-@import "~taro-ui/dist/style/components/icon.scss";
+@import "~taro-ui/dist/style/components/icon.scss";
+
+.index {
+    width: 100vw;
+    height: 100vh;
+    background: #E4ECFF;
+}
+
+.index-bg {
+    width: 100vw;
+    height: 600px;
+}
+
+.item-img {
+    width: 730px;
+    height: 240px;
+    margin-bottom: 16px;
+    margin-left: 10px;
+}
+
+
+.button {
+    background-color: transparent;
+    color: none;
+    border: none;
+    padding: 0px;
+    margin: none;
+    width: 730px;
+    height: 240px;
+}
+
+.button::after {
+    border: none;
+    padding: none;
+}

+ 83 - 19
src/pages/index/index.tsx

@@ -1,39 +1,103 @@
 
-import React, { useEffect } from 'react'
+import React , { useState } from 'react'
 
-import { View, Text } from '@tarojs/components'
+import Taro, { useDidShow } from '@tarojs/taro'
 
-import { AtButton, AtNavBar, AtIcon  } from 'taro-ui'
+import { View, Image, Button } from '@tarojs/components'
 
 import "taro-ui/dist/style/components/button.scss" // 按需引入
 
 import './index.scss'
 
+import { getUserPhoneNumber } from '../../api/user'
 
-// eslint-disable-next-line import/first
-import NavBar from '@/components/NavBar/index'
-
-console.log(NavBar, 'NavBar');
-
-// eslint-disable-next-line import/first
-// import Tip from '@/utils/tip'
-
-// console.log(Tip);
 
 
+import Tip from '../../utils/tip'
 
 const Index: React.FC = () => { 
 
-  useEffect( () => {
-    // Tip.modal().then( res => {
-    //     console.log(res);
-    // })
-  }, [])
+  const [token, setToken] = useState<string>('')
+
+  useDidShow(() => {
+    setToken(Taro.getStorageSync('token'))
+  })
+  
+  // 获取用户手机号
+  const Getphonenumber = async (item: number ,e: any): Promise<void> => {
+    
+    Tip.loading('正在登录...')
+    const { code } = await Taro.login()
+    const data = await getUserPhoneNumber({code, ...e.detail})
+    Tip.loaded()
+
+    Taro.setStorageSync('token', data)
+
+    goPage(item)
+  }
+
+  // 跳转页面
+  const goPage = ( index: number ): void => {
+    if (!Taro.getStorageSync('token')) {
+      Tip.toast('登录错误')
+      return
+    }
+    switch (index) {
+      case 0:
+        Taro.navigateTo({
+           url: '/pages/ScanQrcode/index'
+        });
+      case 1:
+        Taro.navigateTo({
+           url: '/pages/AuthQuery/index'
+        });
+    }
+  }
+
+  const RenderItem = (item: number) => {
+    
+    const noHasPhoneEle = (
+      <Button 
+        className='button' 
+        open-type='getPhoneNumber'
+        onGetPhoneNumber={(e) => Getphonenumber(item, e)}
+      >
+          <Image
+            className='item-img' 
+            src={require(`../../assets/home/home${item}.png`)}
+          />
+      </Button>
+    )
+
+    const hasPhoneELe = (
+      <Image
+        className='item-img' 
+        src={require(`../../assets/home/home${item}.png`)}
+        onClick={() => goPage(item)}
+      />
+    )
+
+    return (
+      <React.Fragment>
+        {
+          token ? hasPhoneELe : noHasPhoneEle
+        }
+      </React.Fragment>
+    )
+  }
 
   return (
     <View className='index'>
-      <NavBar title='navbar' icon={<AtIcon value='chevron-left' size='20' color='#000'></AtIcon>} />
-
+      <Image className='index-bg'  src={require('../../assets/home/bg.png')} />
+      {
+        [0, 1].map( item => (
+          <React.Fragment key={item}>
+          {
+            RenderItem(item)
+          }
+          </React.Fragment>
+        ))
+      }
     </View>
   )
 

+ 21 - 3
src/service/config.ts

@@ -4,14 +4,32 @@
  *  后台返回的状态码从这里修改 一般有 code status state
  * 
  */
-export const errorKey: string = 'code'
+export const errorKey: string = 'status'
 
 /**
  *  错误码
  */
-export const errorCode: number = 0
+export const errorCode: number = 200
 
 
 /**
  * 错误描述
- */
+ */
+
+
+/**
+ * 请求的baseUrl
+ * 
+ */
+
+// eslint-disable-next-line import/no-mutable-exports
+export let baseUrl = '2'
+
+if (process.env.NODE_ENV === 'development') {
+    baseUrl = 'http://verify.test.luojigou.vip:8899'
+    // baseUrl = 'http://192.168.1.21:8091'
+} else {
+    baseUrl = 'http://192.168.1.21:8091'
+}
+
+ 

+ 65 - 28
src/service/request.ts

@@ -1,6 +1,7 @@
 import Taro from '@tarojs/taro'
 import Tip from '../utils/tip'
-import { errorKey, errorCode } from './config'
+import { reloadlogin } from '../api/user'
+import { errorKey, errorCode, baseUrl as BASEURL } from './config'
 
 type paramsType = {
     baseUrl?: string,
@@ -13,42 +14,78 @@ type paramsType = {
 }
 
 // 错误处理
-const errorHandle = (statusCode: number, code: number,  message: string, url: string) => {
-    console.log(code, 'code');
-    
-    if (statusCode !== 200) {
+const errorHandle = (statusCode: number, code: number,  message: string, url: string, params: paramsType) => {
+    console.log(message, 'code');
+    if (code === errorCode) {
+        // 请求很不错
+    } else if (code === 403) {
+
+    }
+    else if (statusCode !== 200) {
         Tip.toast('啊哦, 您的网络出了一点小问题')
-    } else if (code === 500) {
+        throw new Error(`${url} ---> 接口请求失败`)
+    }  else if (code !== errorCode) {
         Tip.toast(message)
-    } else if (code !== errorCode) {
-        Tip.toast('网络开了小差,刷新一下试试')
-        throw new Error(`${url}接口请求失败`)
+        throw new Error(`${url} ---> 接口请求失败`)
     }
 }
 
+
 // 请求
-export const request = async (params: paramsType) => {
-    const {baseUrl, url, method, data, header, timeout, responseType} = params
-    const result = await Taro.request({
-        url: baseUrl + url,
-        method: method || 'GET',
-        data,
-        header: {
-            'Content-Type': 'application/json',
-            ...header
-        },
-        timeout,
-        responseType
-    });
+
+export type responseType = {
+    readonly [key: string]: any
+}
+
+// Promise< responseType | responseType[]>
+
+export const request =  (params: paramsType): Promise<any> => {
     
-    // eslint-disable-next-line no-shadow
-    const { statusCode  } = result
-    const { message, data: Data } = result.data
-    console.log(Data);
+    const { baseUrl, url, method, data, header, timeout, responseType} = params
+    return new Promise( async resolve => {
+        const result = await Taro.request({
+            url: (baseUrl || BASEURL) + url,
+            method: method || 'GET',
+            data,
+            header: {
+                'Content-Type': 'application/json',
+                token: Taro.getStorageSync('token'),
+                ...header
+            },
+            timeout,
+            responseType
+        });
+        
+        // eslint-disable-next-line no-shadow
+        const { statusCode  } = result
+        const { msg, data: Data } = result.data
     
-    errorHandle (statusCode, result.data[errorKey], message, baseUrl + url)
+        errorHandle (statusCode, result.data[errorKey], msg, (baseUrl || BASEURL) + url, params)
+
+        if (result.data.status === 403) {
+          // token失效, 刷新token, 并重发请求
+          console.log('????');
+            Tip.loading()
+            Taro.login({
+                success: res => {
+                    console.log(res);
+                    const { code: Code } = res
+                    reloadlogin(Code).then ( async _ => {
+                        Taro.setStorageSync('token', _.id)
+                        resolve(await request(params))
+                    })
+                }
+            })
+            Tip.loaded()
+
+            return 
+        }
+
+        resolve(Data)
+    }).catch( e => e) 
+
 
-    return Data
+    // return Data
     
 }
 

+ 2 - 0
src/utils/tip.ts

@@ -2,6 +2,8 @@ import Taro from '@tarojs/taro'
 
 type iconType = "success" | "loading" | "none"
 
+
+
 export default class Tip {
     loading: boolean;