Используйте ant design для разработки полноценной серверной системы

JavaScript

Вот что сказатьant designизvueверсия иreactиспользование версии. Два фреймворка здесь не рассматриваютсяvueа такжеreactнижний слой.

vue муравей дизайн проект

Это тестовый проект.

vue ant design

Поскольку используется весь набор фреймворков, то мы следуемvue ant designПроцесс идет волнообразно.

Рекомендуемое использованиеyarnустановить~

# 安装脚手架
yarn global add @vue/cli

# 初始化项目
vue create antd-demo

# 引入vue ant design
yarn add ant-design-vue

Тогда мы непосредственноmain.jsИмпортируется глобально в файл

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

Vue.use(Antd)

использоватьaxiosИнтерфейс операции. Мы можем справиться с этим в соответствии с реальной ситуацией:

// 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)
  }
)

Тогда давайте рассмотрим управление интерфейсом:

# api目录
- api
  - basic_config
    - device.js
    - ...
  - index.js

Выше находится каталог базового управления API, который представлен здесь.device.jsа такжеindex.js入口документ.

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

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

export default {
  getDeviceList
}

Далее монтируем интерфейс на прототип:

// 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在原型上
}

После этого настройте адрес прокси:

// 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

используйте прямо здесь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... и т. д.

В использованииvueа такжеreactверсияant designДля разработки фоновой системы я все же предпочитаю использовать ее самreact ant designДля разработки, конечно, это выбирается в соответствии с реальной ситуацией команды и бизнеса. правильный,typescriptЭто действительно полезно,2020Теперь вы можете подумать о том, чтобы внедрить его в проект.

Чтобы увидеть больше сообщений в блоге, перейдите по ссылкеmy blogs

innocent