Write the Code. Change the World.

分类目录
7月 28

项目弄好了,就要做发布的准备。主要是部署的非根目录的配置。

这里,配置在根目录下的 admin 目录。

修改 config/config.ts,增加下边的配置:

  …
  base: '/admin/',
  outputPath: '../../public/admin',
  publicPath: '/admin/',
  manifest: {
    basePath: '/admin/',
  },

修改 nginx, 增加下边的配置:

    location /admin  {
        index index.html index.htm;
        try_files $uri $uri/ /admin/index.html;
    }
7月 28

linux 下使用 ant design pro 安装依赖的时候,会出现 /bin/sh: 1: umi: not found 问题。需要更改编译模式。

cd /bin

ls -lh sh

# 结果 lrwxrwxrwx 1 root root 4 Jan 21  2020 sh -> dash

下边将 dash 改成 bash。

sudo dpkg-reconfigure dash

# 选择 no 保存即可。

# 然后再执行 ls -lh sh 发现结果是

lrwxrwxrwx 1 root root 4 Jul 28 11:09 sh -> bash

好了,就这样了。

7月 24

还是那句话,喜欢简洁,有强迫症,就是想弄。那么,从路由和注册登录开始。先去掉其他路由,仅仅保存注册登录和welcome。去掉其他页面,从零开始。

修改路由

编辑 /config/config.ts,修改路由配置如下:

  routes: [
    {
      path: '/user',
      layout: false,
      routes: [
        {
          name: 'login',
          path: '/user/login',
          component: './user/auth',
        },
        {
          name: 'register',
          path: '/user/register',
          component: './user/auth',
        }
      ],
    },
    {
      path: '/welcome',
      name: 'welcome',
      icon: 'smile',
      component: './Welcome',
    },
    {
      path: '/',
      redirect: '/welcome',
    },
    {
      component: './404',
    },
  ],

注册和路由都进同一个 component, 然后根据路由进行不同的渲染。
继续阅读

7月 23

ant design pro v5 在 /src/components/ 下暴露一些顶栏以及底栏的功能。可以在这里进行其功能定义。之前就说过,ant design pro 很多地方不完美,需要自己去打造和改变。

作为一个疯狂的极简的完美追求者, 打开 /src/components/RightContent/ 下的 index.tsx,删掉只剩下这么点东东了。

  return (
    <Space className={className}>
      <Avatar />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
    </Space>
  );

然后就只剩下头像和昵称了。

删掉 /src/components/HeaderSearch 这个目录。如果需要什么,再自己扩展。删掉不需要的引用。

修改 Avatar,暴露出个人中心等 dropMenu。虽然暴露了,可没有对应的路由页面,点击是 404 。如果想关掉,去掉 menu 设置。如果想扩展 dropMenu 的功能,可以在 ./AvatarDropdown 里边修改逻辑。

<Avatar  menu={true} />

额外

如何利用 React Hooks API 做全局状态管理?

https://umijs.org/plugins/plugin-initial-state#loading

7月 23

ant design pro 版本总是更新,总是没稳定下来。前段时间 v5 也出来了,和 v4 差别蛮大的。就样式来说,我更喜欢宽点的侧边栏,更喜欢将侧边栏伸缩按钮放在顶部。更喜欢暴露更多的 layout,去定义自己想要的。喜欢更简洁,更少的展示的元素。不是专业研究前端的,核心东西还是没深入。从零开始创建项目以及变更项目吧。

安装

yarn create umi

# 选择 ant design pro
# 选择 v5
# 等待下载

# 安装依赖包
yarn 

# 启动,先看看效果(默认样式太丑陋,兼职无语)
yarn start

# git 操作
git init
git add .
git commit -m 'ant-design-pro-v5-initialize'

到此, ant design pro v5 已经安装完成。但页面太丑陋,和曾经的页面完全不是一个样。页面丑陋是由 div 和 css 决定的。下边修改下配置,使得样式稍微好看一点。

继续阅读

4月 10

官网文档:https://pro.ant.design/docs/i18n-cn

使用

  1. 先配置。
可以配置在 src/locales/ 中,也可以配置在各自的组件目录中。
比如,新建了一个模块 TestForm, locales 就可以放在这里边。个人觉得,各个模块的 locales 放在各自的目录下表好。包括 model service 这些。

# locales/zh-CN.ts
export default {
    'login.formlogin.login': '登录',
    'login.formlogin.register': '注册',
    'login.formlogin.account': '账号',
    'login.formlogin.account-placeholder': '请输入账号',
}  
# locales/zh-TW.ts
export default {
    'login.formlogin.login': '登錄',
    'login.formlogin.register': '註冊',
    'login.formlogin.account': '賬號',
    'login.formlogin.account-placeholder': '请输入賬號',
}
  1. 再使用。
# 使用 FormattedMessage 或 使用 formatMessage 

import { FormattedMessage, formatMessage } from "umi";

<Form.Item label={<FormattedMessage 
id="login.formlogin.account" />} 
rules={[{ required: true, message: formatMessage({id:'login.formlogin.account-placeholder'}) }]}>
    <Input placeholder={formatMessage({id:'login.formlogin.account-placeholde'})}/>
</Form.Item>

不过,使用 formatMessage 的时候,会报下边的警告。

Warning: Using this API will cause automatic refresh when switching languages, please use useIntl or injectIntl.

使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl。

可是对 placeholder 如果不使用 formatMessage 又不行。真为难。

下边一个简单的 login 的列子

不喜欢官方的登录注册页,不仅繁琐,还不好看。

index.tsx

import { connect } from 'umi';
import { ConnectState } from '@/models/connect';

import FormLogin from './FormLogin';

const Login = () => {
    const onLoginSubmit = (value:any) => {
        console.log(value);
    }

    return (
        <FormLogin onLoginSubmit={onLoginSubmit} ></FormLogin>
    );
};


export default connect(({ login, loading }: ConnectState) => ({
    userLogin: login,
    submitting: loading.effects['login/login'],
}))(Login);

locales/zh-CN.ts

export default {
    'login.formlogin.login': '登录',
    'login.formlogin.register': '注册',
    'login.formlogin.account': '账号',
    'login.formlogin.account-placeholder': '请输入账号',
    'login.formlogin.account-rule': '请输入正确的账号格式(手机号码)',
    'login.formlogin.password': '密码',
    'login.formlogin.password-placeholder': '请输入密码',
    'login.formlogin.password-rule': '密码不能为空',
    'login.formlogin.remember-password': '记住密码',
    'login.formlogin.forget-password': '忘记密码',
    'login.formlogin.none-account': '如果没有账号,请',
}

FormLogin/index.tsx

import React from "react";
import styles from "./index.less";
import { FormattedMessage, formatMessage } from "umi";
import { Card, Form, Input, Button, Checkbox } from "antd";

const itemLayout = {
  labelCol: {
    xs: { span: 24 },
    sm: { span: 6 },
  },
  wrapperCol: {
    xs: { span: 24 },
    sm: { span: 12 },
  },
};

const tailLayout = {
  wrapperCol: {
    xs: { span: 24 },
    sm: { offset:6, span: 12 }
  },
};

const NormalLoginForm = (props:any) => {
  return (
    <Card bordered={false} title={<FormattedMessage id='login.formlogin.login' />} style={{ width: 720 }}>
      <Form
        {...itemLayout}
        initialValues={{ remember: true }}
        onFinish={props.onLoginSubmit}
      >
        <Form.Item name="account" label={<FormattedMessage id='login.formlogin.account' />} rules={[{ required: true, pattern: /^1[3456789]\d{9}$/ , message: <FormattedMessage id='login.formlogin.account-rule' /> }]}>
          <Input placeholder={ formatMessage({ id: 'login.formlogin.account-placeholder' })} />
        </Form.Item>

        <Form.Item name="password" label={<FormattedMessage id="login.formlogin.password" />} rules={[{ required: true, message: <FormattedMessage id='login.formlogin.password-rule' /> }]}>
          <Input.Password placeholder={formatMessage({ id: 'login.formlogin.password-placeholder' })} />
        </Form.Item>

        <Form.Item {...tailLayout} name="remember" valuePropName="checked">
          <Checkbox>
            <FormattedMessage id="login.formlogin.remember-password" />
          </Checkbox>
        </Form.Item>

        <Form.Item {...tailLayout}>
          <Button type="primary" htmlType="submit">
            <FormattedMessage id='login.formlogin.login' />
          </Button>

          <Button type="link" href="https://baidu.com" target="_blank">
            <FormattedMessage id='login.formlogin.forget-password' />
          </Button>
        </Form.Item>

        <Form.Item {...tailLayout} className="other-way">
            <span><FormattedMessage id='login.formlogin.none-account' /></span>
            <Button type="link" href="https://baidu.com" size="small">
              <FormattedMessage id='login.formlogin.register' />
            </Button>
        </Form.Item>
      </Form>
    </Card>
  );
};

export default (props:any) => (
  <div className={styles.container}>
    <div id="form-login">
      <NormalLoginForm onLoginSubmit={props.onLoginSubmit} />
    </div>
  </div>
);

FormLogin/index.less

.container {
  height: 100%;

  :global {
    #form-login {
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 100%;
      background-color: rgba(255,0,0,0.1);

      .login-form {
        width: 100%;
        max-width: 720px;
      }
    }

    .other-way {
      margin-top: 20px;
      margin-bottom: 0;
    }
  }
}

到目前为止,service,model 都是空的。要实现登录注册的功能,就得完善它们。