Ant Design 定制示例
介绍
Ant Design (Pro) 相关文档:
创建项目
Ant Design Pro 生成项目模板,参考 https://beta-pro.ant.design/docs
$ npm i @ant-design/pro-cli -g
$ pro create x-ui
$ cd x-ui
$ tyarn
$ tyarn start
$ tyarn start:dev
开发工具
目录结构
- 参考:https://pro.ant.design/zh-CN/docs/folder/
- 配置参考 https://v3.umijs.org/zh-CN/config
src/pages/document.ejs
配置加载页,包括对应的 logo 等src/app.tsx
getInitialState
做权限初始化,如认证等信息src/models
全局初始化数据,应用加载前初始化用户、权限、菜单等数据,其它地方使用 const { initialState, setInitialState } = useModel('@@initialState');
- 页面组件的定制,需要在
routes.ts
配置,参考 plugin-layout
相关扩展
定制
- 国际化删除
src/locales
对应的文件即可精简
代码生成
参考维生成器
umi generate
umi g
umi g page
umi g page bar --dir
umi g prettier
接口规范
export interface response {
success: boolean; // if request is success
data?: any; // response data
errorCode?: string; // code for errorType
errorMessage?: string; // message display to user
showType?: number; // error display type: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 page
traceId?: string; // Convenient for back-end Troubleshooting: unique request ID
host?: string; // onvenient for backend Troubleshooting: host of current access server
}
{
list: [
],
current?: number,
pageSize?: number,
total?: number,
}
{
"success": true,
"data": {},
"errorCode": "1001",
"errorMessage": "error message",
"showType": 2,
"traceId": "someid",
"host": "10.1.1.1"
}
# 对于简单的可以如下:
{
"success": true,
"data": {},
"errorMessage": "error message"
}
Mock
基于 OpenAPI 生成 SDK
基于 OpenAPI 生成前端调用代码(参考):
配置 config/config.ts
import { join } from 'path';
export default defineConfig({
...
openAPI: [
{
requestLibPath: "import { request } from 'umi'",
// 或者使用在线的版本
// schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
schemaPath: join(__dirname, 'oneapi.json'),
mock: false, // 为 true 会在 mock 目录生成 mock 文件
projectName: 'swagger',
},
...
- 生成 services 代码到 src/services/目录下
npm openapi
生成 openapi 文档到 src/services/swagger
目录,然后就可以在页面中调用
- requestInterceptors 注入 token 等,具体配置参考
权限
// src/access.ts
export default function (initialState: { currentUser?: API.CurrentUser | undefined }) {
const { currentUser } = initialState || {};
return {
canAdmin: currentUser && currentUser.access === 'admin',
};
}
静态发布时,配置 API 的 baseURL
/**
* @name request 配置,可以配置错误处理
* 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
* @doc https://umijs.org/docs/max/request#配置
*/
export const request: RequestConfig = {
baseURL: 'https://proapi.azurewebsites.net',
...errorConfig,
};
路由方式
- 参考
- Ant Design Pro 使用的 Umi 可以使用两种路由方式:
browserHistory
使用 browserHistory 则需要服务器做好处理 URL 的准备,处理应用启动最初的 / 这样的请求应该没问题,但当用户来回跳转并在 /users/123 刷新时,服务器就会收到来自 /users/123 的请求,这时你需要配置服务器能处理这个 URL 返回正确的 index.html,否则就会出现 404 找不到该页面的情况- 建议在配置中开启
exportStatic
,这样编译后的 dist
目录会对每一个路由都生成一个 index.html
,从而每个路由都能支持 deeplink 直接访问 - 强烈推荐使用默认的
browserHistory
hashHistory
使用 hashHistory 时浏览器访问到的始终都是根目录下 index.html,取井号(/#/users/123
)后面的字符作为路径
自定义参数配置
export default defineConfig({
define: {
APP_URL: 'http://dev.xiexianbin.cn:8000', // 当前SaaS发布的URL地址
},
...
declare const APP_URL: string;
css/less
- CSS Modules 的基本原理很简单,就是对每个类名(非 :global 声明的)按照一定规则进行转换,保证它的唯一性
多主题
参考 switch-theme
jsx
{/* jsx 单行注释 */}
{/*
多行注释
*/}
发布
npm run build
server {
listen 80;
# gzip config
gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
root /usr/share/nginx/html;
location / {
# 用于配合 browserHistory使用
try_files $uri $uri/index.html /index.html;
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
# rewrite ^/(.*)$ https://preview.pro.ant.design/$1 permanent;
}
location /api {
proxy_pass https://ant-design-pro.netlify.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
# 如果有资源,建议使用 https + http2,配合按需加载可以获得更好的体验
listen 443 ssl http2 default_server;
# 证书的公私钥
ssl_certificate /path/to/public.crt;
ssl_certificate_key /path/to/private.key;
location / {
# 用于配合 browserHistory使用
try_files $uri $uri/index.html /index.html;
}
location /api {
proxy_pass https://ant-design-pro.netlify.com;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
自动修复 lint 的错误
npm run lint:fix
websocket 代理
// config/proxy.js
export default {
dev: {
// websocket代理
'/ws/': {
target: 'ws://localhost:1323',
ws: true,
logLevel: 'debug',
secure: false,
pathRewrite: {
'^/ws': '',
},
},
},
}
组件总览
Tailwind CSS
F&Q
CORS 问题
需求是实现 http://dev.xiexianbin.cn:8001 调用 http://dev.xiexianbin.cn:8888 时,将 .xiexianbin.cn 的 cookie 带过去
Access to fetch at 'http://dev.xiexianbin.cn:8888/api/v1/user' from origin 'http://dev.xiexianbin.cn:8001' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
export async function user(options?: { [key: string]: any }) {
return request<{
data: API.User;
}>('/api/v1/user', {
method: 'GET',
credentials: 'include', // 添加改行实现将 .xiexianbin.cn 的 cookie 带过去
...(options || {}),
});
}
// origin := c.Request.Header.Get("Origin")
// c.Header("Access-Control-Allow-Origin", origin)
c.Writer.Header().Set("Access-Control-Allow-Origin", c.Request.Header.Get("Origin") // 这一行是核心
c.Writer.Header().Set("Access-Control-Max-Age", "86400")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Access-Control-Allow-Origin, Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
cors 示例