使用ant design開發完整的後臺系統

這裏要說的是ant designvue版和react版本的使用。這裏不考慮到兩種框架vuereact的底層。javascript

vue ant design 項目

這是一個測試平臺的項目。vue

vue ant design

由於使用的是整套的框架,那麼咱們按照vue ant design流程走一波。java

推薦使用yarn進行安裝~react

# 安裝腳手架
yarn global add @vue/cli

# 初始化項目
vue create antd-demo

# 引入vue ant design
yarn add ant-design-vue
複製代碼

以後咱們就直接在main.js文件中全局引入ios

// main.js
import Vue from 'vue'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.less'

Vue.use(Antd)
複製代碼

使用axios操做接口。咱們能夠根據實際狀況進行處理:git

// request.js
import Vue from 'vue'
import notification from 'ant-design-vue/es/notification'
import JSONbig from 'json-bigint' // 處理大數據, 建議大數字後端變成字符串傳回

// 建立 auth axios 實例
const auth = axios.create({
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest'
  },
  baseURL: 'api', // api base_url
  timeout: 10 * 60 * 1000, // 請求超時時間 10 分鐘
  transformResponse: [function (data) {
    return JSONbig.parse(data)
  }],
})

// 請求攔截器
auth.interceptors.request.use(config => {
  const token = Vue.ls.get(ACCESS_TOKEN)
  if (token) {
    config.headers[ 'Authorization' ] = 'JWT '+ token // 讓每一個請求攜帶自定義 token 請根據實際狀況自行修改
  }
  return config
}, err)

// 響應攔截器
auth.interceptors.response.use(
  response => {
    if (response.code === 10140) {
      loginTimeOut()
    } else {
      return response.data
    }
  }, 
  error => { // 錯誤處理
    // 超時
    if(error.response && error.response.status === 500){
      notice({
        title: `服務端異常 ${error.response.statusText}`,
      }, 'notice', 'error', 5)
      return
    }
    // ...
    notice({
        title: `${error.response && error.response.data && error.response.data.msg}`,
    }, 'notice', 'error', 5)
  }
)
複製代碼

那麼咱們來考慮下對接口的管理:github

# api目錄
- api
  - basic_config
    - device.js
    - ...
  - index.js
複製代碼

上面是api的基本管理的目錄,這裏呈現device.jsindex.js入口文件。typescript

// device.js
import { auth } from '@/utils/request'

export function getDeviceList(params) {
  return auth({
    url: '/path/to/url',
    method: 'get',
    params
  })
}

export default {
  getDeviceList
}
複製代碼

接下來咱們在原型上掛載接口:json

// index.js
import bc_device from './basis_config/device'
// ...

const api = {
  bc_device
}

export default api

export const ApiPlugin = {}

ApiPlugin.install = function (Vue, options) {
  Vue.prototype.api = api // 掛載api在原型上
}
複製代碼

以後,調整下要代理地址:axios

// vue.config.js

const HOST = '0.0.0.0';
const PORT = '9002';
const DEV_URL = 'http://10.***.**.***' // 測試環境
module.exports = {
  devServer: {
    host: HOST,
    port: PORT,
    https: false,
    hotOnly: false,
    proxy: { // 配置跨域
      '/api': {
        //要訪問的跨域的api的域名
        target: `${DEV_URL}`,
        ws: true,
        changOrigin: true,
        // pathRewrite: {
        // '^/api': ''
        // }
      }    
    }
  }
  // ...
};
複製代碼

完成上面的配置和修改後,那麼咱們能夠搬磚了...

以剛纔配置的bc_device接口爲例:

# 部分頁面目錄
- views
  - basis_config
    - comp # 這裏是私有組件的存放
    - device_manage.vue
複製代碼
<!-- device_manage.vue -->
<template>
  <div class="device_manage">
    <a-table 
      :rowKey="row => row.id"
      :columns="columns"
      :dataSource="data"
      :pagination="false"
      :loading="loading"
      />
  </div>
</template>
<script>
export default {
  name: 'device_manage',
  data () {
    const columns = [{
      dataIndex: 'operation',
      title: '操做'
    },
    // ...
    ]
    return {
      columns,
      data: [],
      loading: false,
    }
  },
  mounted() {
    this.getList()
  },
  methods: {
    // 獲取列表數據
    getLists() {
      let vm = this
      vm.loading = true
      const params = {}
      vm.api.bc_device.getDeviceList(params).then(res => {
        if(res.code === '00000') {
          vm.data = res.data || []
        } else {
          vm.$message.warning(res.msg || '獲取設備列表失敗!')
        }
	  }).finally(() => {
        vm.loading = false
      })
    }
  }
}
</script>
複製代碼

能夠愉快地在搭建好的框架裏面添加東西了。

react ant design 項目

使用react ant design開發的項目是一個信息配置後臺系統。

react ant design

這裏直接使用Ant Design Pro開發的。

這裏的安裝方法根據官網執行:

# 新建一個空的文件夾做爲項目目錄,並在目錄下執行:
yarn create umi

# 選擇`ant-design-pro`
Select the boilerplate type (Use arrow keys)
❯ ant-design-pro  - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
  app             - Create project with a simple boilerplate, support typescript.
  block           - Create a umi block.
  library         - Create a library with umi.
  plugin          - Create a umi plugin.

複製代碼

我這裏結合了typescript來開發,推薦使用。

咱們使用集成的umi-request

// request.ts
/** * request 網絡請求工具 * 更詳細的 api 文檔: https://github.com/umijs/umi-request */
import { getStore, removeStore } from '@/utils/storage';

import { extend } from 'umi-request';

import { notification } from 'antd';

import { stringify } from 'querystring';

import { router } from 'umi';

/** * 異常處理程序 */
const errorHandler = (error: {
  response: Response;
  data: { code: number; message: string };
}): Response => {
  const { response, data } = error;
  if (response && response.status) {
    // const errorText = codeMessage[response.status] || response.statusText;
    const errorText = data ? data.message : '錯誤了!';

    const { status } = response;

    notification.error({
      message: `請求錯誤 - ${status}`,
      description: errorText,
    });

    /** * 10000 IP change * 10001 token timeout */
    if (response.status === 401 && (data.code === 10000 || data.code === 10001)) {
      router.replace({
        pathname: '/user/login',
        search: stringify({
          redirect: window.location.href,
        }),
      });
      removeStore('token');
    }
  } else if (!response) {
    notification.error({
      description: '您的網絡發生異常,沒法鏈接服務器',
      message: '網絡異常',
    });
  }
  return response;
};

/** * 配置request請求時的默認參數 */
const request = extend({
  errorHandler, // 默認錯誤處理
  credentials: 'include', // 默認請求是否帶上cookie
});

// 請求攔截器
request.interceptors.request.use((url, options) => {
  const token = getStore('token') || ''; // 401的時候要清空下token
  if (token) {
    options.headers = {
      // 處理header中的token
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: `** ${token}`,
    };
  }
  return {
    url,
    options: { ...options },
  };
});

request.interceptors.response.use(async (response: any) => response);

export default request;
複製代碼

處理接口請求:

// 接口的部分目錄
- services
  - port.ts
  - ...
複製代碼
import request from '@/utils/request';

// 獲取配置端口列表
export async function getNginxPort(params: object) {
  return request('/path/to/url', {
    method: 'get',
    params,
  });
}
複製代碼

在執行api請求操做以前,咱們配置下代理~

// config/proxy.ts
/** * 在生產環境 代理是沒法生效的,因此這裏沒有生產環境的配置 * The agent cannot take effect in the production environment * so there is no configuration of the production environment * For details, please see * https://pro.ant.design/docs/deploy */
export default {
  dev: {
    '/api/': {
      target: 'http://***.**.***.**',
      changeOrigin: true,
      pathRewrite: { '^': '' },
    },
  },
};

複製代碼

那麼咱們來實現下分配端口的列表數據請求:

// pages/port/index.tsx
import React, { Component } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Table, message, Tag, Row, Input, Button } from 'antd';
import {
  SearchOutlined,
  DeleteOutlined,
  PlusOutlined,
  InfoCircleOutlined,
} from '@ant-design/icons';
import { getNginxPort, postNginxPortItem, deleteNginxPortItem } from '@/services/port';
import moment from 'moment';

const { confirm } = Modal;

interface NginxPortProps {}

interface NginxPortState {
  data: object[];
  loading: boolean;
  current: number;
  pageSize: number;
  total: number;
  showSizeChanger: boolean;
  showQuickJumper: boolean;
}

class NginxPort extends Component<NginxPortProps, NginxPortState> {
  constructor(props: any) {
    super(props);
    this.state = {
      data: [],
      loading: false,
      current: 1,
      pageSize: 10,
      total: 0,
      showSizeChanger: true, // 展現頁條數與否
      showQuickJumper: true, // 展現跳轉與否
      search: ''
    };
  }

  componentDidMount() {
    this.getList();
  }

  getList = () => {
    const rn = this;
    const { pageSize, current } = rn.state;
    rn.setState({
      loading: true,
    });
    getNginxPort({
      page_size: pageSize,
      page: current
    })
      .then((res: any) => {
        if (res.code === 200) {
          rn.setState({
            data: res.data.lists || [],
            total: res.data.total || 0,
          });
        } else {
          message.warn(res.msg || '獲取端口列表失敗!');
        }
      })
      .finally(() => {
        rn.setState({
          loading: false,
        });
      });
  };

  // 改變表格
  onchange = (pagination: any) => {
    this.setState(
      {
        current: pagination.current,
        pageSize: pagination.pageSize,
      },
      this.getList,
    );
  };

  render() {
    const columns = [
      {
        title: '端口號',
        dataIndex: 'port',
        key: 'port',
        width: 120,
      },
      {
        title: '服務代號',
        dataIndex: 'sercode',
        key: 'sercode',
      },
      {
        title: 'GIT地址',
        dataIndex: 'git',
        key: 'git',
      },
      {
        title: '類型',
        dataIndex: 'type',
        key: 'type',
        render: (type: any) => <Tag color="blue">{type}</Tag>,
        width: 120,
      },
      {
        title: '建立時間',
        dataIndex: 'created_on',
        key: 'created_on',
        render: (text: number) => <span>{moment(text * 1000).format('YYYY-MM-DD')}</span>,
        width: 120,
      },
    ];
    const {
      data,
      loading,
      total,
      current,
      pageSize,
      showSizeChanger,
      showQuickJumper,
      showModal,
    } = this.state;
    return (
      <PageHeaderWrapper title={false}>
        <Table
          scroll={{ x: 1200 }}
          dataSource={data}
          columns={columns}
          loading={loading}
          onChange={this.onchange}
          rowKey={(record: any) => record.id}
          pagination={{
            total,
            current,
            pageSize,
            showTotal: (_total) => `共 ${_total} 條數據`,
            showSizeChanger,
            showQuickJumper,
          }}
        />
      </PageHeaderWrapper>
    );
  }
}

export default NginxPort;
複製代碼

好了,能夠安靜地打代碼了。

後話

嗯~

根據實際狀況增長功能,好比圖表展現你要選啥實現:echart, bizchart...等等

在使用vuereact版本的ant design開發後臺系統,本身仍是比較偏向使用react ant design來開發,固然,這是根據團隊和業務實際狀況來選擇。對了,typescript真的挺好用的,都2020年了,能夠考慮在項目中引入使用。

博文更多內容請前往my blogs

innocent
相關文章
相關標籤/搜索