hejh 1 年間 前
コミット
baba0c842b
5 ファイル変更427 行追加284 行削除
  1. 5 6
      .umirc.ts
  2. 3 1
      package.json
  3. 70 0
      public/server.js
  4. 119 120
      src/pages/home/index.less
  5. 230 157
      src/pages/home/index.tsx

+ 5 - 6
.umirc.ts

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

+ 3 - 1
package.json

@@ -30,13 +30,15 @@
     "umi": "^3.5.36"
   },
   "devDependencies": {
+    "@types/express": "^4.17.17",
     "@types/react": "^17.0.0",
     "@types/react-dom": "^17.0.0",
     "@umijs/preset-react": "1.x",
     "@umijs/test": "^3.5.36",
+    "express": "^4.18.2",
     "lint-staged": "^10.0.7",
     "prettier": "^2.2.0",
     "typescript": "^4.1.2",
     "yorkie": "^2.0.0"
   }
-}
+}

+ 70 - 0
public/server.js

@@ -0,0 +1,70 @@
+// import express from 'express';
+const express = require('express');
+const app = express();
+
+app.use(express.static('./'));
+
+app.use(async (req, res) => {
+  // 或者从 CDN 上下载到 server 端
+  // const serverPath = await downloadServerBundle('http://cdn.com/bar/umi.server.js');
+  const render = require('./umi.server');
+  res.setHeader('Content-Type', 'text/html');
+  var _html = `
+    <!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
+    />
+    <link rel="stylesheet" href="/umi.css" />
+    <script>
+      window.routerBase = "/";
+    </script>
+    <script>
+      //! umi version: 3.5.37
+    </script>
+  </head>
+  <body>
+    <div id="root"></div>
+
+    <script src="/umi.js"></script>
+  </body>
+</html>
+`;
+
+  const context = {};
+  const { html, error, rootContainer } = await render({
+    // 有需要可带上 query
+    path: req.url,
+    context,
+
+    // 可自定义 html 模板
+    htmlTemplate: _html,
+
+    // 启用流式渲染
+    // mode: 'stream',
+
+    // html 片段静态标记(适用于静态站点生成)
+    // staticMarkup: false,
+
+    // 扩展 getInitialProps 在服务端渲染中的参数
+    // getInitialPropsCtx: {},
+
+    // manifest,正常情况下不需要
+  });
+
+  // support stream content
+  res.send(html);
+  // if (content instanceof Stream) {
+  //     html.pipe(res);
+  //     html.on('end', function () {
+  //         res.end();
+  //     });
+  // } else {
+  //     res.send(res);
+  // }
+});
+
+app.listen(8088);

+ 119 - 120
src/pages/home/index.less

@@ -1,148 +1,147 @@
 .container {
-    max-width: 1200px;
-    margin: auto;
+  max-width: 1200px;
+  margin: auto;
+}
+
+html,
+body {
+  margin: 0;
 }
 
 .home {
-    .home-back {
-        width: 100%;
+  .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-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;
 
-    .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;
-                    }
-                }
-            }
-        }
+    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;
 
-    .home-ad {
-        background-color: #F3F5FE;
-        padding-top: 132px;
-        padding-bottom: 160px;
-        display: flex;
-        flex-direction: column;
-        align-items: center;
-        justify-content: center;
+        & > img {
+          width: 100%;
+          height: 100%;
+        }
 
-        .home-ad-row {
-            margin-top: 112px;
+        .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;
 
-            img {
-                width: 100%;
+            & > span {
+              font-size: 50px;
             }
+          }
+
+          .home-qa-img-row-item-absolute-subtitle {
+            font-size: 14px;
+            font-weight: 400;
+          }
         }
+      }
     }
+  }
 
-    .home-static {
-        height: 723px;
-        background: linear-gradient(315deg, #496CF2 0%, #7663FF 100%);
-        display: flex;
-        flex-direction: column;
-        align-items: center;
-        justify-content: center;
+  .home-ad {
+    background-color: #f3f5fe;
+    padding-top: 132px;
+    padding-bottom: 160px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
 
-        color: #fff;
+    .home-ad-row {
+      margin-top: 112px;
 
-        .home-title {
-            color: #fff;
+      img {
+        width: 100%;
+      }
+    }
+  }
 
-            &-sub {
-                color: #fff;
-                margin-bottom: 94px;
-            }
-        }
+  .home-static {
+    height: 723px;
+    background: linear-gradient(315deg, #496cf2 0%, #7663ff 100%);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
 
-        .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;
-            }
-        }
+    color: #fff;
 
-        &-title {
-            font-size: 38px;
-        }
+    .home-title {
+      color: #fff;
 
-        .home-static-btn {
-            margin-top: 38px;
-            height: 50px;
-            border-radius: 50px;
-            color: #723BED;
-            width: 200px;
-        }
+      &-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;
-}
+  padding: 40px !important;
+}

+ 230 - 157
src/pages/home/index.tsx

@@ -6,166 +6,239 @@ import { useRef, useState } from 'react';
 import './index.less';
 
 const homeList0 = [
-    {
-        title: "传统获得客效率低,成本高",
-        content: "3000个白名单里可能只能挖掘出一个意向客户,员工信心不足,线路成本与人工成本均居高不下"
-    },
-    {
-        title: "客户资源易流失",
-        content: "高价挖掘的意向客户,面临员工离职带走客户和员工飞单的风险,无法形成客户资产,资源全部在业务员手上"
-    },
-    {
-        title: "跨部门沟通成本高",
-        content: "线下上门客户填写个人信息受法律监管,机构对于各类纸质资料不易保存,上门客户服务情况无法掌握,跨部门沟通成本高"
-    },
-]
+  {
+    title: '传统获得客效率低,成本高',
+    content:
+      '3000个白名单里可能只能挖掘出一个意向客户,员工信心不足,线路成本与人工成本均居高不下',
+  },
+  {
+    title: '客户资源易流失',
+    content:
+      '高价挖掘的意向客户,面临员工离职带走客户和员工飞单的风险,无法形成客户资产,资源全部在业务员手上',
+  },
+  {
+    title: '跨部门沟通成本高',
+    content:
+      '线下上门客户填写个人信息受法律监管,机构对于各类纸质资料不易保存,上门客户服务情况无法掌握,跨部门沟通成本高',
+  },
+];
 const homeList1 = [
-    {
-        title: "轻松获客",
-        content: "通过惠融易客推广获客,轻松获取意向客户,有效降低获客成本95%"
-    },
-    {
-        title: "客户管理",
-        content: "通过惠融易客客户管理系统,科学高效管理企业客户资料,开成公司资产,员工离职一键收回所有权限,客户跟进情况一目了然"
-    },
-    {
-        title: "业务管理",
-        content: "通过惠融易客客户管理系统记录跟进,客户从上门到成交的各个环节均可清晰化、信息化记录,有效提高效率与服务质量"
-    },
-]
+  {
+    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>
+  const [targetDate, setTargetDate] = useState<number>();
+  const ref = useRef<FormInstance>();
+  const [open, setOpen] = useState(false);
+  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={open}
+      >
+        <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>
-                </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>
+                  </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>
-                </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>
+  );
+};