Browse Source

frist commit

Peggy 1 năm trước cách đây
commit
eee77391d8

+ 16 - 0
.editorconfig

@@ -0,0 +1,16 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/npm-debug.log*
+/yarn-error.log
+/yarn.lock
+/package-lock.json
+
+# production
+/dist
+
+# misc
+.DS_Store
+
+# umi
+/src/.umi
+/src/.umi-production
+/src/.umi-test
+/.env.local

+ 8 - 0
.prettierignore

@@ -0,0 +1,8 @@
+**/*.md
+**/*.svg
+**/*.ejs
+**/*.html
+package.json
+.umi
+.umi-production
+.umi-test

+ 11 - 0
.prettierrc

@@ -0,0 +1,11 @@
+{
+  "singleQuote": true,
+  "trailingComma": "all",
+  "printWidth": 80,
+  "overrides": [
+    {
+      "files": ".prettierrc",
+      "options": { "parser": "json" }
+    }
+  ]
+}

+ 18 - 0
.umirc.ts

@@ -0,0 +1,18 @@
+import { defineConfig } from 'umi';
+
+export default defineConfig({
+  nodeModulesTransform: {
+    type: 'none',
+  },
+  routes: [
+    { path: '/', component: '@/pages/home/index' },
+  ],
+  fastRefresh: {},
+  proxy: {
+    '/api': {
+      'target': 'http://yhcrm-admin-api.internal.jiebide.xin:881',
+      'changeOrigin': true,
+      'pathRewrite': { '^/api': '' },
+    },
+  },
+});

+ 15 - 0
README.md

@@ -0,0 +1,15 @@
+# umi project
+
+## Getting Started
+
+Install dependencies,
+
+```bash
+$ yarn
+```
+
+Start the dev server,
+
+```bash
+$ yarn start
+```

+ 0 - 0
mock/.gitkeep


+ 42 - 0
package.json

@@ -0,0 +1,42 @@
+{
+  "private": true,
+  "scripts": {
+    "start": "umi dev",
+    "build": "umi build",
+    "postinstall": "umi generate tmp",
+    "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
+    "test": "umi-test",
+    "test:coverage": "umi-test --coverage"
+  },
+  "gitHooks": {
+    "pre-commit": "lint-staged"
+  },
+  "lint-staged": {
+    "*.{js,jsx,less,md,json}": [
+      "prettier --write"
+    ],
+    "*.ts?(x)": [
+      "prettier --parser=typescript --write"
+    ]
+  },
+  "dependencies": {
+    "@ant-design/pro-components": "^2.3.54",
+    "@ant-design/pro-layout": "^6.5.0",
+    "ahooks": "^3.7.4",
+    "antd": "^5.2.1",
+    "axios": "^1.3.3",
+    "react": "17.x",
+    "react-dom": "17.x",
+    "umi": "^3.5.36"
+  },
+  "devDependencies": {
+    "@types/react": "^17.0.0",
+    "@types/react-dom": "^17.0.0",
+    "@umijs/preset-react": "1.x",
+    "@umijs/test": "^3.5.36",
+    "lint-staged": "^10.0.7",
+    "prettier": "^2.2.0",
+    "typescript": "^4.1.2",
+    "yorkie": "^2.0.0"
+  }
+}

+ 33 - 0
src/apis.ts

@@ -0,0 +1,33 @@
+import { message } from "antd";
+import axios from "axios"
+
+
+export const getSmsCode = (userMobile: string) => {
+    return axios.post("/api/collect/sendSms", {
+        sceneType: "loanofficial",
+        userMobile,
+    })
+        .then(p => {
+            if (p.status === 200 && p.data.code === 0) {
+                message.success("发送成功");
+                return p;
+            }
+            message.error(p.data.msg);
+            return null;
+        })
+}
+
+export const submit = (values: any) => {
+    return axios.post("/api/collect/customer", {
+        sceneType: "loanofficial",
+        ...values
+    })
+        .then(p => {
+            if (p.status === 200 && p.data.status === "Succ") {
+                message.success("申请成功");
+                return p;
+            }
+            message.error(p.data.msg);
+            return null;
+        })
+}

BIN
src/assets/guanbi@2x.png


BIN
src/assets/img_home.png


BIN
src/assets/img_home_ad_0.png


BIN
src/assets/img_home_ad_1.png


BIN
src/assets/img_home_ad_2.png


BIN
src/assets/img_home_ad_3.png


BIN
src/assets/img_home_ad_4.png


BIN
src/assets/img_home_ad_5.png


BIN
src/assets/img_home_modal_0.png


BIN
src/assets/img_home_modal_1.png


BIN
src/assets/img_home_modal_2.png


BIN
src/assets/img_home_modal_3.png


BIN
src/assets/img_home_modal_4.png


BIN
src/assets/img_home_qs_0_0.png


BIN
src/assets/img_home_qs_0_1.png


BIN
src/assets/img_home_qs_0_2.png


BIN
src/assets/img_home_qs_1_0.png


BIN
src/assets/img_home_qs_1_1.png


BIN
src/assets/img_home_qs_1_2.png


+ 12 - 0
src/hooks/useTimer.ts

@@ -0,0 +1,12 @@
+import { useInterval } from "ahooks";
+import { useState } from "react";
+
+
+
+export const useTimer = () => {
+    const [count, setCount] = useState(0);
+
+    useInterval(() => {
+        setCount(count + 1);
+    }, 1000);
+}

+ 148 - 0
src/pages/home/index.less

@@ -0,0 +1,148 @@
+.container {
+    max-width: 1200px;
+    margin: auto;
+}
+
+.home {
+    .home-back {
+        width: 100%;
+    }
+
+    .home-title {
+        font-size: 42px;
+        font-weight: 400;
+        text-align: center;
+
+        &-sub {
+            text-align: center;
+            font-size: 22px;
+            font-weight: 400;
+            margin-top: 28px;
+            color: #888888;
+        }
+    }
+
+    .home-qa {
+        padding: 170px 0;
+
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+
+
+
+        .home-qa-img-row {
+            margin-top: 103px;
+
+            .home-qa-img-row-item {
+                max-width: 490px;
+                position: relative;
+
+                &>img {
+                    width: 100%;
+                    height: 100%;
+                }
+
+                .home-qa-img-row-item-absolute {
+                    position: absolute;
+                    top: 0;
+                    left: 0;
+                    width: 100%;
+                    height: 100%;
+                    padding: 32px 24px;
+                    color: #fff;
+                    display: flex;
+                    flex-direction: column;
+                    justify-content: space-around;
+
+                    .home-qa-img-row-item-absolute-title {
+                        font-size: 22px;
+                        font-weight: bold;
+
+                        &>span {
+                            font-size: 50px;
+                        }
+                    }
+
+                    .home-qa-img-row-item-absolute-subtitle {
+                        font-size: 14px;
+                        font-weight: 400;
+                    }
+                }
+            }
+        }
+
+
+    }
+
+    .home-ad {
+        background-color: #F3F5FE;
+        padding-top: 132px;
+        padding-bottom: 160px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+
+        .home-ad-row {
+            margin-top: 112px;
+
+            img {
+                width: 100%;
+            }
+        }
+    }
+
+    .home-static {
+        height: 723px;
+        background: linear-gradient(315deg, #496CF2 0%, #7663FF 100%);
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+
+        color: #fff;
+
+        .home-title {
+            color: #fff;
+
+            &-sub {
+                color: #fff;
+                margin-bottom: 94px;
+            }
+        }
+
+        .home-static-num {
+            display: flex;
+            justify-content: center;
+            align-items: center;
+
+            &-wrap {
+                padding: 0 24px;
+                border-radius: 9px;
+                background-color: #fff;
+                color: #723BED;
+                font-size: 60px;
+            }
+        }
+
+        &-title {
+            font-size: 38px;
+        }
+
+        .home-static-btn {
+            margin-top: 38px;
+            height: 50px;
+            border-radius: 50px;
+            color: #723BED;
+            width: 200px;
+        }
+    }
+
+
+}
+
+.ant-modal-body {
+    padding: 40px !important;
+}

+ 171 - 0
src/pages/home/index.tsx

@@ -0,0 +1,171 @@
+import { getSmsCode, submit } from '@/apis';
+import { ModalForm, ProFormText } from '@ant-design/pro-components';
+import { useCountDown, useRequest } from 'ahooks';
+import { Button, Col, FormInstance, message, Modal, Row } from 'antd';
+import { useRef, useState } from 'react';
+import './index.less';
+
+const homeList0 = [
+    {
+        title: "传统获得客效率低,成本高",
+        content: "3000个白名单里可能只能挖掘出一个意向客户,员工信心不足,线路成本与人工成本均居高不下"
+    },
+    {
+        title: "客户资源易流失",
+        content: "高价挖掘的意向客户,面临员工离职带走客户和员工飞单的风险,无法形成客户资产,资源全部在业务员手上"
+    },
+    {
+        title: "跨部门沟通成本高",
+        content: "线下上门客户填写个人信息受法律监管,机构对于各类纸质资料不易保存,上门客户服务情况无法掌握,跨部门沟通成本高"
+    },
+]
+const homeList1 = [
+    {
+        title: "轻松获客",
+        content: "通过惠融易客推广获客,轻松获取意向客户,有效降低获客成本95%"
+    },
+    {
+        title: "客户管理",
+        content: "通过惠融易客客户管理系统,科学高效管理企业客户资料,开成公司资产,员工离职一键收回所有权限,客户跟进情况一目了然"
+    },
+    {
+        title: "业务管理",
+        content: "通过惠融易客客户管理系统记录跟进,客户从上门到成交的各个环节均可清晰化、信息化记录,有效提高效率与服务质量"
+    },
+]
+
+export default () => {
+    const [targetDate, setTargetDate] = useState<number>();
+    const ref = useRef<FormInstance>();
+    const [countdown] = useCountDown({ targetDate });
+    const result = useRequest(async (phone: string) => {
+        const p = await getSmsCode(phone);
+        p && setTargetDate(Date.now() + 60000);;
+    }, { manual: true })
+    return (
+        <div className="home" >
+            <ModalForm
+                formRef={ref}
+                width={500}
+                onFinish={async (values) => {
+                    await submit(values);
+                }} title="申请试用" open={true} >
+                <ProFormText fieldProps={{ addonBefore: <img style={{ width: 15, height: 15 }} src={require("../../assets/img_home_modal_0.png")} /> }} rules={[{ required: true }]} name="companyName" placeholder="请输入您的公司名称" />
+                <ProFormText fieldProps={{ addonBefore: <img style={{ width: 15, height: 15 }} src={require("../../assets/img_home_modal_1.png")} /> }} rules={[{ required: true }]} name="address" placeholder="请选择所在城市" />
+                <ProFormText fieldProps={{ addonBefore: <img style={{ width: 15, height: 15 }} src={require("../../assets/img_home_modal_2.png")} /> }} rules={[{ required: true }]} name="customName" placeholder="请输入您的姓名" />
+                <ProFormText fieldProps={{ addonBefore: <img style={{ width: 15, height: 15 }} src={require("../../assets/img_home_modal_3.png")} /> }} rules={[{ required: true }]} name="phone" placeholder="请输入您的联系方式" />
+                <ProFormText fieldProps={{
+                    addonAfter: <a style={{ display: "inline-block", width: 100 }} onClick={() => {
+                        if (!result.loading && countdown === 0) {
+                            var phone = ref.current?.getFieldValue("phone") as string;
+                            if (new RegExp("^1[0-9]{10}$").test(phone)) {
+                                result.run(phone);
+                            }
+                            else {
+                                message.error("请输入正确的手机号")
+                            }
+                        }
+                    }} >{countdown === 0 ? "获取验证码" : Math.round(countdown / 1000)}</a>, addonBefore: <img style={{ width: 15, height: 15, }} src={require("../../assets/img_home_modal_4.png")} />
+                }} rules={[{ required: true }]} name="verifyCode" placeholder="请输入验证码" />
+            </ModalForm>
+            <img className="home-back" src={require('../../assets/img_home.png')} />
+            <div className='home-qa' >
+                <div className='home-title' >为什么选择惠融易客</div>
+                <div className='home-title-sub'>与传统方式相比较,惠融易客的优势又都有哪些?</div>
+                <div className='home-qa-img-row' >
+                    <div className='container' >
+                        <Row gutter={[24, 24]} >
+                            {
+                                homeList0.map((p, i) => {
+                                    return (
+                                        <Col span={8} key={p.title} >
+                                            <div className={`home-qa-img-row-item `} >
+                                                <img src={require(`../../assets/img_home_qs_0_${i}.png`)} />
+                                                <div className='home-qa-img-row-item-absolute' >
+                                                    <div className='home-qa-img-row-item-absolute-title' >
+                                                        {p.title}
+                                                    </div>
+                                                    <div className='home-qa-img-row-item-absolute-subtitle' >
+                                                        {p.content}
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </Col>
+                                    )
+                                })
+                            }
+                            {
+                                homeList1.map((p, i) => {
+                                    return (
+                                        <Col span={8} key={p.title} >
+                                            <div className={`home-qa-img-row-item `} >
+                                                <img src={require(`../../assets/img_home_qs_1_${i}.png`)} />
+                                                <div className='home-qa-img-row-item-absolute' >
+                                                    <div className='home-qa-img-row-item-absolute-title' >
+                                                        <span>0{i + 1}</span>  {p.title}
+                                                    </div>
+                                                    <div className='home-qa-img-row-item-absolute-subtitle' >
+                                                        {p.content}
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </Col>
+                                    )
+                                })
+                            }
+                        </Row>
+                    </div>
+                </div>
+            </div>
+            <div className='home-ad' >
+                <div className='container' >
+                    <div className='home-title' >精准获客</div>
+                    <div className='home-title-sub'>多渠道投放对接,帮助企业搭建推广产品矩阵</div>
+                    <Row gutter={[100, 24]} className="home-ad-row" >
+                        {
+                            [...Array(6).keys()].map(p => {
+                                return (
+                                    <Col span={8} >
+                                        <img src={require(`../../assets/img_home_ad_${p}.png`)} />
+                                    </Col>
+                                )
+                            })
+                        }
+                    </Row>
+                </div>
+            </div>
+            <div className='home-static' >
+                <div className='container' >
+                    <div className='home-title' >精准获客</div>
+                    <div className='home-title-sub'>多渠道投放对接,帮助企业搭建推广产品矩阵</div>
+                    <Row align="middle" gutter={32} >
+                        <Col className='home-static-title' >
+                            已加入
+                        </Col>
+                        <Col  >
+                            <Row gutter={12} >
+                                {
+                                    "1233333".split("").map(p => {
+                                        return (
+                                            <Col flex={1} className="home-static-num" >
+                                                <div className='home-static-num-wrap' >
+                                                    {p}
+                                                </div>
+                                            </Col>
+                                        )
+                                    })
+                                }
+                            </Row>
+                        </Col>
+                        <Col className='home-static-title' >
+                            人
+                        </Col>
+                    </Row>
+                    <div style={{ textAlign: "center" }} >
+                        <Button className='home-static-btn' >立即申请试用</Button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    )
+}

+ 3 - 0
src/pages/index.less

@@ -0,0 +1,3 @@
+.title {
+  background: rgb(121, 242, 157);
+}

+ 9 - 0
src/pages/index.tsx

@@ -0,0 +1,9 @@
+import styles from './index.less';
+
+export default function IndexPage() {
+  return (
+    <div>
+      <h1 className={styles.title}>Page index</h1>
+    </div>
+  );
+}

+ 37 - 0
tsconfig.json

@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    "target": "esnext",
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "importHelpers": true,
+    "jsx": "react-jsx",
+    "esModuleInterop": true,
+    "sourceMap": true,
+    "baseUrl": "./",
+    "strict": true,
+    "paths": {
+      "@/*": ["src/*"],
+      "@@/*": ["src/.umi/*"]
+    },
+    "allowSyntheticDefaultImports": true
+  },
+  "include": [
+    "mock/**/*",
+    "src/**/*",
+    "config/**/*",
+    ".umirc.ts",
+    "typings.d.ts"
+  ],
+  "exclude": [
+    "node_modules",
+    "lib",
+    "es",
+    "dist",
+    "typings",
+    "**/__test__",
+    "test",
+    "docs",
+    "tests"
+  ]
+}

+ 10 - 0
typings.d.ts

@@ -0,0 +1,10 @@
+declare module '*.css';
+declare module '*.less';
+declare module '*.png';
+declare module '*.svg' {
+  export function ReactComponent(
+    props: React.SVGProps<SVGSVGElement>,
+  ): React.ReactElement;
+  const url: string;
+  export default url;
+}