What is delicate

delicate logo

delicate A lightweight and distributed task scheduling platform written in rust.

features

  • Friendly UI: [Front-end] Convenient management of tasks & executors, monitoring their status and supporting manual maintenance etc.

  • Flexible Operations: Flexible task operations, support for limiting the maximum number of parallelism in a single node, time zone settings corresponding to cron expressions, scheduling modes (single, fixed number, constantly repeating), the ability to manually trigger tasks at any time, manually terminate task instances, and view task logs online.

  • High Availability: Delicate supports unlimited horizontal expansion. It's easy to achieve high availability and performance by deploying as many Delicate servers and executors.

  • High Performance: Lightweight and essential features speed up the performance, The basic resource overhead for delicate is roughly (less than 0.1% cpu usage, with about 10m of memory.)

  • Observability: There are many meaningful statistics periodically in a readable way.

  • Upgrade: Dynamic upgrade of the system (upgrade is done by obtaining the latest source code and performing database migration.

  • Reusability: Excutor provides restful-api that allows user applications to maintain custom tasks.

Delicate Roadmap

Product Principles

  1. Operability & Experience. Designed with easy-to-understand features that provide a user-friendly system experience, the job is done between silky smooth operations.

Business Extensibility

  • Easy to develop new features with Battery-included Delicate.
  • Easy to operate/easy to install.

Roadmap 2021

NameIssueDescription
I18nInternationalization, convenient for users in different countries and regions.
Operation LogRecord the user's operation behavior.
Permission ManagementHumanized permission management to protect machine task resources and maintain system security.
Multiple login protocolsSupport multiple login protocols to open up the user system within the enterprise and enhance user experience.
Machine resource panelPowerful online resource panel with online visualization of machine / task support for multiple user actions.
FailoverAutomatically migrate tasks when a node is down.
Upgrade to actix-web 4Wait for actix-web 4 stable which will support with tokio 1 , So that scheduler & executor communication can using RPC (tonic | tarpc).

ExecutorGroup

Executor Group which corresponds to a service, or a business.

Executor Group

Configuration-1

NameTypeDescriptionRequired
namestringGroup nameYes
descriptionstringGroup descriptionYes
tagstringGroup tagYes

ExecutorProcessor

Executor Processor which corresponding to a physical machine, or a container.

Executor Group

Configuration-2

NameTypeDescriptionRequired
namestringProcessor nameYes
descriptionstringProcessor descriptionYes
tagstringProcessor tagYes
hoststringProcessor host , No spaces between strings, (example: 12.34.56.78:9080 )Yes
machine_idintProcessor machine-id , Value range (0 to 1023). In order to mark custom machine serial numbers and to be able to using snowflake algorithm generate unique task-instance-idYes

ExecutorProcessorBind

Executor Processor Bind, which corresponds to the association between a Executor Group and a Executor Processor, and the task needs to select the machine(Executor Processor) to execute through the association Executor Processor Bind.

Tip:

When there are hundreds of tasks associated with a certain Executor Processor Bind, it is easy to switch the machine that executes the task if you want to. Just modify the Executor Processor associated with the Executor Processor Bind, then hundreds of tasks will be removed from the old machine and executed on the new machine.

Executor Processor Bind

Configuration-3

NameTypeDescriptionRequired
group_idintGroup idYes
executor_idintProcessor idYes
namestringBinding nameYes
weightintResource Occupancy WeightsYes

Task

Task which corresponds to a set of commands given by the user that will be executed on the machine to generate task instances.

Task

Configuration-4

NameTypeDescriptionRequired
namestringTask nameYes
descriptionstringTask sescriptionYes
commandstringTask Commands for task executionYes
frequencystringFrequency for task executionYes
cron_expressionstringCron Expression for task executionYes
timeoutintCron Timeout for task executionYes
retry_timesintRetry times for task executionYes
retry_intervalintRetry interval for task executionYes
tagstringTask's tagYes
binding_ids[int]Task's bingdingYes

TaskInstance

Task Instance which corresponds to an instance of a running task (e.g a running process).

TaskInstance

Configuration-5

NameTypeDescriptionRequired
idintUnique id generated by snowflake algorithmYes
task_idintTask's idYes
namestringTask name (snapshot)Yes
descriptionstringTask description (snapshot)Yes
commandstringTask's idYes
frequencystringTask's frequency (snapshot)Yes
cron_expressionstringTask's cron_expression (snapshot)Yes
maximum_parallel_runnable_numintTask 'smaximum_parallel_runnable_num (snapshot)Yes
tagstringTask's tag (snapshot)Yes
statusintTask's Status Included(Running = 1,Finished = 2,AbnormalEnding = 3,TimeoutEnding = 4,TmanualCancellation = 5,Unknown = 81)Yes
created_timedatetimeTask Instance creation timeYes
updated_timedatetimeTask Instance Update timeYes
executor_processor_idintExecutor processor idYes
executor_processor_namestringExecutor processor name (snapshot)Yes
executor_processor_hoststringExecutor processor hostYes

User

User which corresponds to users of the system.

PS: When the system is first installed, you can set the initial user in .env.

User

Configuration-6

NameTypeDescriptionRequired
user_namestringUser account, must be uniqueYes
nick_namestringUser nicknameYes
mobilestringMobie-number(unique)Yes
emailstringEmail(unique)Yes
certificatestringPassword credentials (the station saves the password, the station does not save or save the token)Yes

StatusDataAggregation

delicate aggregates the task scheduling for the latest day, including: (successful scheduling, timeout, manual cancellation, abnormal end, normal end, etc.), which we can view in the home dashboard.

Security

There are two levels of security, 0 and 1. This can be adjusted by setting the environment variable DELICATE_SECURITY_LEVEL.

At level 0, the executor and scheduler communicate without security signatures.

Under level 1, executor and scheduler will use RSA key for authentication when binding, and then dynamically generate a token, which will be stored in the database of scheduler, and each subsequent communication will use token & sha2 hash algorithm for signature authentication.

After the deployment, we can start using the delicate related functions.

First login via .env (INITIAL_ADMINISTRATOR_USER_NAME) , the initialized user.

First, we go to execution-resources-executor-node to maintain delicate-executor into our system as a machine resource and perform the activation operation.

Then, go to the execution-resources-execution-groups menu to add our resource group and do binding with the corresponding execution-node to generate binding items.

Next, go to the Task List to add our scheduling task and associate our binding item.

When a task starts scheduling, a scheduling log is generated, and we can click the More button -> View Log for the specified task under the task list.

Each task run log corresponds to a task instance, which can be cancelled at any time when it is running. Tasks that have finished running, or have timed out, can be viewed with standard output and standard errors generated by the task execution.

For more content, please see doc.

在部署之后,我们可以开始使用delicate的相关功能。

首先通过 .env (INITIAL_ADMINISTRATOR_USER_NAME) , 初始化的用户进行登陆。

首先,我们进入执行资源-执行节点delicate-executor作为机器资源维护进入我们的系统,并执行激活操作。

然后,进入执行资源-执行组菜单添加我们的资源组,并与对应的执行节点做绑定生成绑定项

下一步,进入任务列表添加我们的调度任务,并关联我们的绑定项.

当任务开始调度后,生成调度日志,我们可以通过任务列表下的指定任务点击更多按钮 -> 查看日志

每一个任务的运行日志都对应着一个任务实例, 在运行中的任务实例是可以随时取消的。已经运行完成,或者超时的任务可以查看任务执行后产生的标准输出与标准错误。

更多内容请查看doc。

delicate A lightweight and distributed task scheduling platform written in rust.

delicate logo

Features

  • Friendly UI: [Front-end] Convenient management of tasks & executors, monitoring their status and supporting manual maintenance etc.

  • Flexible Operations: Flexible task operations, support for limiting the maximum number of parallelism in a single node, time zone settings corresponding to cron expressions, scheduling modes (single, fixed number, constantly repeating), the ability to manually trigger tasks at any time, manually terminate task instances, and view task logs online.

  • High Availability: Delicate supports unlimited horizontal expansion. It's easy to achieve high availability and performance by deploying as many Delicate servers and executors.

  • High Performance: Lightweight and essential features speed up the performance, The basic resource overhead for delicate is roughly (less than 0.1% cpu usage, with about 10m of memory.)

  • Observability: There are many meaningful statistics periodically in a readable way.

  • Upgrade: Dynamic upgrade of the system (upgrade is done by obtaining the latest source code and performing database migration.

architecture

Technology-stack

Backend: Rust
main-dependencies: (actix-web & diesel & delay-timer & serde & tracing)

Front-end: antd-admin (React)

Ui: Ant Design

Database: mysql , postgres (plan support)

Quick-start

What's next#

At the this year, we announced our 2021 roadmap for Delicate. So we will continue to follow this roadmap.

Roadmap

Thanks

Thank you!

We would like to thank the whole community and code contributors. In particular, thanks to the code contributors from the past two months: Walker-os

Thanks to users reporting spelling mistakes on the documentation. This is always appreciated. Thanks to users joining us provide feedbacks, discuss features, and get assistance!

Renderings

delicate 一个轻量的分布式的任务调度平台通过rust编写.

delicate logo

特性

  • 友好的用户界面: [前端]方便地管理任务和执行器,监控其状态,支持手动维护运行中的任务等。

  • 灵活的操作: 灵活的任务操作,支持限制单个节点的最大并行数,与cron表达式相对应的时区设置,调度模式(单一、固定数量、不断重复),能够在任何时候手动触发任务,手动终止任务实例,在线查看任务日志。

  • 高可用性: Delicate支持横向扩展。通过部署尽可能多的Delicate服务器和执行器,很容易实现高可用性和性能。

  • 高性能: 轻量级和基本功能加快了性能,`delicate'的基本资源开销大约是(小于0.1%的cpu使用率,10m的内存.)

  • 可观察性: 有许多有意义的统计数据定期以图表的方式展现。

  • 升级: 系统的动态升级(升级是通过获得最新的源代码和进行数据库迁移.)

architecture

技术栈

后端( scheduler & executor ): Rust
主要的依赖: (actix-web & diesel & delay-timer & serde & tracing)

前端: antd-admin (React)

Ui: Ant Design

数据库: mysql , postgres (计划支持)

Quick-start

下一步是什么

在今年的计划中,我们宣布了2021年Delicate的路线图。因此,我们将继续遵循这个路线图.

Roadmap

感谢

谢谢你

我们要感谢整个社区和代码贡献者。特别是,感谢过去两个月的代码贡献者: Walker-os

感谢用户报告文档中的拼写错误, 这非常感谢大家。 感谢用户加入我们,提供反馈,讨论功能,并获得帮助!

效果图

delicate-rs

Delicate

delicate A lightweight and distributed task scheduling platform written in rust.

GitHub issues Build License PRs Welcome

Features

  • Internationalization, extracting translation fields from source code, loading language packs on demand
  • Dynamic permissions, different permissions for different menus
  • Elegant and beautiful, Ant Design system
  • Mock data, local data debugging

Usage

  1. Clone project code.
git clone https://github.com/BinChengZhao/delicate.git my-project
cd my-project
  1. Installation dependence.
sudo npm install --global yarn
sudo yarn global add umi
sudo yarn install
sudo yarn build
  1. Start local server.
sudo yarn start
  1. After the startup is complete, open a browser and visit http://localhost:7000, If you need to change the startup port, you can configure it in the .env file.

More instructions at 。

Browsers support

Modern browsers.

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
IE11, Edgelast 2 versionslast 2 versionslast 2 versionslast 2 versions

Contributing

We very much welcome your contribution, you can build together with us in the following ways :smiley:

  • Use Ant Design Pro in your daily work.
  • Submit GitHub issuess to report bugs or ask questions.
  • Propose Pull Request to improve our code.

delicate-rs

Delicate

delicate A lightweight and distributed task scheduling platform written in rust.

GitHub issues Build License PRs Welcome

Features

  • Internationalization, extracting translation fields from source code, loading language packs on demand
  • Dynamic permissions, different permissions for different menus
  • Elegant and beautiful, Ant Design system
  • Mock data, local data debugging

Usage

  1. Clone project code.
git clone https://github.com/BinChengZhao/delicate.git my-project
cd my-project
  1. Installation dependence.
sudo npm install --global yarn
sudo yarn global add umi
sudo yarn install
sudo yarn build
  1. Start local server.
sudo yarn start
  1. After the startup is complete, open a browser and visit http://localhost:7000, If you need to change the startup port, you can configure it in the .env file.

More instructions at 。

Browsers support

Modern browsers.

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
IE11, Edgelast 2 versionslast 2 versionslast 2 versionslast 2 versions

Contributing

We very much welcome your contribution, you can build together with us in the following ways :smiley:

  • Use Ant Design Pro in your daily work.
  • Submit GitHub issuess to report bugs or ask questions.
  • Propose Pull Request to improve our code.

Layout

Add a new layout

Take a new layout named secondary as an example to make the route starting with secondary use this layout.

  1. Add related configuration in src/utils/config.js. For details, please refer to layouts.
   layouts: [
           {
               name: 'primary',
               include: [/.*/],
               exclude: [/(\/(en|zh))*\/login/, /(\/(en|zh))*\/secondary\/(.*)/],
           },
           {
               name: 'secondary',
               include: [/(\/(en|zh))*\/secondary\/(.*)/],
           },
   ],
  1. Add the secondary layout component to the src/layouts/BaseLayout.js file.
   import SecondaryLayout from './SecondaryLayout'

   const LayoutMap = {
     primary: PrimaryLayout,
     public: PublicLayout,
     secondary: SecondaryLayout,
   }
  1. Add the SecondaryLayout.js file to the src/layouts/ directory.
   import React from 'react'

   export default ({ children }) => {
     return (
       <div>
         <h1>Secondary</h1>
         {children}
       </div>
     )
   }
  1. Add a secondary/index.js file to the src/pages/ directory.
   import React from 'react'

   export default ({ children }) => {
     Return <div>Secondary page Content</div>
   }
  1. Finally, start the development mode npm run start, open http://localhost:7000/secondary/ and you will see the page for the secondary layout.

Configuration

You can do some custom configuration in /src/utils/config.js:

siteName

  • Type String

    Configure the site name, apply it to the login box, and display the title text at the top of the sidebar.

  • Type: String

    Configure the copyright notice to apply to the login page, at the bottom of the Primary layout.

logoPath

  • Type: String

    Configure the site logo to apply to the login box and the Logo display at the top of the sidebar.

apiPrefix

  • Type: String

    Configure the prefix of the interface in the project. The interface related documents can be viewed API configuration

fixedHeader

  • Type: String

    Under the Primary layout, whether the top of the page is fixed when scrolling。

layouts

  • Type: Array

    Configuration? Which routes use which layout, unspecified route uses the default layout Public, the project currently has Primary and Public layouts,      The default configuration is as follows:

        layouts: [
            {
                name: 'primary',
                include: [/.*/],
                exclude: [/(\/(en|zh))*\/login/],
            },
        ],
    

    The object properties for each layout are as follows:

    • name - The name of the layout;

    • include - Specifies a list of routing rules that use this layout, which can be a regular expression or a string;

    • exclude - Specifies a list of routing rules that do not use this layout, which can be a regular expression or a string.

Note: exclude takes precedence over include, and the layout previous it has a higher priority than the behind layout. The development process may need to be combined with the layout in the src/layouts directory. For details, see Using Layout.

i18n

  • Type: Object

    Configure internationalization, the default configuration is as follows:

    i18n: {
        languages: [
          {
              key: 'en',
              title: 'English',
              flag: '/america.svg',
          },
          {
              key: 'zh',
              title: '中文',
              flag: '/china.svg',
          },
        ],
        defaultLanguage: 'en',
    }
    

    i18n.languages

    • Type: Array

      Specify which languages the app supports, and the object properties for each language are as follows:

      • key - The key of the language is applied to the page url to distinguish the language, and also corresponds to the language package folder name in the src/locales directory;

      • title - The name of the language, at the bottom of the login page, at the top of the Primary layout, the language switch is displayed;

      • flag - The path of the flag icon of the language, the language switching display at the top of the Primary layout.

i18n.defaultLanguage

  • Type: String

    Configure the default language.

FAQ

Most asked

create new page

1. just copy a page in /src/pages (route here auto generated by [umi](https://umijs.org/guide/router.html#basic-routing))
2. modify namespace/pathToRegexp in task.js
3. modify mock route.js to add a route

Quick Start

Before delving into Ant Design React, a good knowledge base of ReactES2015+Antd Design . Learn about UmiJS , Dva . And properly installed and configured Node.js v8 or above, Git. It would be helpful if you have pre-existing knowledge on those.

Installation

git clone https://github.com/BinChengZhao/delicate.git my-project
cd my-project

Scaffolding

The project layout is as follows:

├── dist/               # Default build output directory
├── mock/               # Mock files 
├── public/             # Static resource 
├── src/                # Source code
│ ├── components/       # Components
│ ├── e2e/              # Integrated Test Case
│ ├── layouts/          # Common Layouts
│ ├── locales/          # i18n resources
│ ├── models/           # Global dva Model
│ ├── pages/            # Sub-pages and templates
│ ├── services/         # Backend Services
│ │ ├── api.js          # API configuration
│ │ └── index.js        # API export
│ ├── themes/           # Themes
│ │ ├── default.less    # Less variable
│ │ ├── index.less      # Global style
│ │ ├── mixin.less      # Less mixin
│ │ └── vars.less       # Less variable and mixin
│ ├── utils/            # Utility
│ │ ├── config.js       # Application configuration
│ │ ├── constant.js     # Static constant
│ │ ├── index.js        # Utility methods
│ │ ├── request.js      # Request function(axios)
│ │ └── theme.js        # Style variables used in js
├── .editorconfig       
├── .env                
├── .eslintrc           
├── .gitignore          
├── .prettierignore     
├── .prettierrc         
├── .stylelintrc.json   
├── .travis.yml         
└── .umirc.js           
└──  package.json      

Development

  1. Install Dependencies.
yarn install

Or

npm install
  1. Start local server.
npm run start
  1. After the startup is complete, open a browser and visit http://localhost:7000, If you need to change the startup port, you can configure it in the .env file.

API configuration

Why

In the use of redux or dva projects, we often write functions like the following service layer to make the code structure clearer, but it is easy to see that we will write a lot of similar code in antd -admin@5.0, using the more concise configuration method to achieve the same function.

export async function login(data) {
  return request({
    url: '/api/v1/user/login',
    method: 'post',
    data,
  })
}

Configuration and use

In the src/services/api.js file, you will see the following configuration object, the object's key is used to call the function name, the object's value is the requested url, the default request method is GET, The format of the value of the other request mode object is 'method url'.

export default {
  ...
  queryUser: '/user/:id',
  queryUserList: '/users',
  updateUser: 'Patch /user/:id',
  createUser: 'POST /user/:id',
  removeUser: 'DELETE /user/:id',
  removeUserList: 'POST /users/delete',
  ...
}

Used in other files

import { queryUser } from 'api'

// in the general file
...
queryUser(option).then(data => console.log(data))
...

/ / Model file
...
yield call(queryUser, option)
...

Method to realize

Refer to the src/services/index.js file to traverse the api configuration. Each property returns the corresponding encapsulated request function.

import request from 'utils/request'
import { apiPrefix } from 'utils/config'

import api from './api'

const gen = params => {
  let url = apiPrefix + params
  let method = 'GET'

  const paramsArray = params.split(' ')
  if (paramsArray.length === 2) {
    method = paramsArray[0]
    url = apiPrefix + paramsArray[1]
  }

  return function(data) {
    return request({
      url,
      data,
      method,
    })
  }
}

const APIFunction = {}
for (const key in api) {
  APIFunction[key] = gen(api[key])
}

module.exports = APIFunction

globalization

Add language

Take Japanese as an example.

i18n

  1. Add a language pack local file, ja is the Japanese language code, and a list of languages ​​that support translation 有道智云, the src/locales/ja/messages.json file will be generated after running the following command.

    npm run add-locale ja
    
  2. Extract the fields in the code that need to be translated, ie <Trans>?message</Trans>, t`message in the message field, run the following command after src/locales/ja /messages.json will appear after the extracted field configuration.

    npm run extract
    

    You will see the following information:

    Catalog statistics:
    ┌─────────────┬─────────────┬─────────┐
    │ Language    │ Total count │ Missing │
    ├─────────────┼─────────────┼─────────┤
    │ en (source) │     52      │    -    │
    │ ja          │     52      │   52    │
    │ zh          │     52      │    0    │
    └─────────────┴─────────────┴─────────┘
    
  3. At the same time, we have added the relevant configuration in src/utils/config.js.

    {
        ...
        i18n: {
            languages: [
                ...
                {
                    key:'ja',
                    title: '日本語',
                    flag: '/japanese.svg',
                },
            ],
        },
    }
    

    Routing related effects, after the configuration npm run start takes effect after restart.

  4. Use the built-in commands for automatic translation. You will see the translated configuration in src/locales/ja/messages.json.

    npm run trans:only
    

    You will see the following information:

    start: en -> ja
    ...
    youdao: en -> ja: Unpublished -> 未発表
    youdao: en -> ja: Update -> 更新
    youdao: en -> ja: Update User -> ユーザーの更新
    youdao: en -> ja: Username -> 名
    ...
    All translations have been completed.
    

    npm run trans will execute npm run extract and npm run trans:only in order.

  5. Finally, you can adjust the inaccurate fields in src/locales/ja/messages.json. Start the development mode npm run start, open http://localhost:7000/ja/login and you will see the Japanese version of the app.

HTTP request

this project use axios for http service, file located in src/utils/request.js

Custom Header

As for privilege access or modify cookie, you could add header param by yourself

axios.defaults.headers.common['Authorization'] = 'token'

Or

axios.interceptors.request.use(function (config) {
  config.headers.token = window.localStorage.getItem('token');
  return config;
}, function (error) {
  return Promise.reject(error);
});

Deploy

After the development is completed and verified in the development environment, it needs to be deployed to our users.

i18n

Build

First execute the following command,

npm run build

After a few seconds, the output should look like this:

> delicate-rs@5.0.0-beta build /Users/delicate/delicate-web
> umi build

[21:13:17] webpack compiled in 43s 868ms
 DONE  Compiled successfully in 43877ms          21:13:17

File sizes after gzip:

  1.3 MB     dist/vendors.async.js
  308.21 KB  dist/umi.js
  45.49 KB   dist/vendors.chunk.css
  36.08 KB   dist/p__chart__highCharts__index.async.js
  33.53 KB   dist/p__user__index.async.js
  22.36 KB   dist/p__chart__ECharts__index.async.js
  4.21 KB    dist/p__dashboard__index.async.js
  4.06 KB    dist/umi.css
  ...

The build command will package all resources, including JavaScript, CSS, web fonts, images, html, and more. You can find these files in the dist/ directory.

If you have requirements for using HashHistory , deploying html to non-root directories, statics, etc., check out [Umi Deployment] (https://umijs.org/en/guide/deploy.html).

Local verification

Local verification can be done via serve before publishing.

$ yarn global add serve
$ serve ./dist

Serving!

- Local:            http://localhost:5000
- On Your Network:  http://{Your IP}:5000

Copied local address to clipboard!

Access http://localhost:5000, under normal circumstances, it should be consistent with npm start (The API may not get the correct data).

Deploy

Next, we can upload the static file to the server. If you use Nginx as the Web server, you can configure it in ngnix.conf:

server
	{
		listen       80;
        # Specify an accessible domain name
		server_name web.delicate-rs.com;
        # The directory where the compiled files are stored
		root  /home/www/delicate-web/dist;

        # Proxy server interface to avoid cross-domain
		location /api {
			 proxy_pass http://*.*.*.*:8090/api;
		}

         Because the front end uses BrowserHistory, it will route backback to index.html
		location / {
				index  index.html;
				try_files $uri $uri/ /index.html;
		}
	}

Restart the web server and access http://web.delicate-rs.com , You will see the correct page.

nginx -s reload

Similarly, if you use Caddy as a web server, you can do this in Caddyfile:

web.delicate-rs.com {
        gzip
        root /home/www/delicate-web/dist
        proxy /api http://localhost:7000

        rewrite {
                if {path} not_match ^/api
                to {path} {path}/ /
        }
}


web.delicate-rs.com/public {
        gzip
        root  /home/www/delicate-web/dist/static/public
}

5.0.0

Optimization

  • Try to use decorators to simplify code writing and improve code readability.

  • API configurization to simplify the way data is obtained.

  • The files in utils are split and each has its own role.

  • Simplify the utils/request file without special handling.

Specification

  • Functions add comments, parameters, return values, etc., ambiguous code adds comments, canonical reference Google JavaScript Style Guide.   

  • Semantic version number, specification participation semantic version 2.0.0.

  • Static code checking, unified code style, will use prettier, stylelint, eslint specification code before code submission.

  • Git submits information normalization, git-commit-emoji-cn.

  • Based on the pre-defined routing of Umi, there is no need to write a routing configuration file.

  • Use React 16 new features such as Fragment, Context, PureComponent, etc.

Features

  • Support internationalization, extract source fields from source code, load language packs on demand, and automatically translate online.

  • Support for the introduction lodash functions on demand.   

  • Support multiple layouts, which rules can be used according to the rules.

  • Support Antd Admin to automatically compile and deploy on Travis.

  • Generate a documentation website using Docsify.

Style

  • Added Antd Admin standalone Logo.

  • Rewrite the overall layout component, optimize the menu, automatic breadcrumb navigation, menu auto-expansion and other logic.

  • The mobile menu is changed to drawer.

Other

  • Discard components such as IconFont, Search, DataTable because they are well supported and replaceable in Antd.

delicate-rs

Delicate

一个轻量的分布式的任务调度平台通过 rust & react 编写.

delicate 的前端项目是基于 "antd-admin "开发的,非常感谢各位。

GitHub issues Build License PRs Welcome

前端特性

  • 国际化,源码中抽离翻译字段,按需加载语言包
  • 动态权限,不同权限对应不同菜单
  • 优雅美观,Ant Design 设计体系
  • Mock 数据,本地数据调试

使用

  1. 下载项目代码。
git clone https://github.com/BinChengZhao/delicate.git my-project
cd my-project
  1. 进入目录安装依赖,国内用户推荐使用 cnpm 进行加速。
sudo npm install --global yarn
sudo yarn global add umi
sudo yarn install
sudo yarn build
  1. 部署: 接下来,我们可以将静态文件上传到服务器。如果你使用Nginx作为Web服务器,你可以在ngnix.conf中配置它:
server
	{
		listen       80;

        # Specify an accessible domain name
		server_name web.delicate-rs.com;

        # The directory where the compiled files are stored
		root  /home/www/delicate-web/dist;

        # Proxy delicate-scheduler server .
		location /api {
            proxy_set_header   X-Forwarded-For $remote_addr;
            proxy_set_header   Host $http_host;
            proxy_pass         http://*.*.*.*:8090;
        }

        # Because the front end uses BrowserHistory, it will 
		# route back to index.html
		location / {
				index  index.html;
				try_files $uri $uri/ /index.html;
		}
	}
  1. 启动完成后,打开浏览器,访问http://yourdomain.com,如果你需要改变启动端口,可以在.env文件中配置,而且你可以在delicate-web/src/utils/envConfig.js中设置delicate-scheduler服务端的请求地址。.

更多信息请参考 。

支持环境

现代浏览器。

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
IE11, Edgelast 2 versionslast 2 versionslast 2 versionslast 2 versions

参与贡献

我们非常欢迎你的贡献,你可以通过以下方式和我们一起共建 :smiley:

  • 在你的公司或个人项目中使用 AntD Admin。
  • 通过 Issue 报告 bug 或进行咨询。
  • 提交 Pull Request 改进代码。

强烈推荐阅读 《提问的智慧》《如何向开源社区提问题》《如何有效地报告 Bug》《如何向开源项目提交无法解答的问题》,更好的问题更容易获得帮助。

布局

新增布局

以新增名为 secondary 的布局为例,使以 secondary 开头的路由都使用该布局。

  1. src/utils/config.js 新增相关配置,参数详细请查看 layouts

    layouts: [
            {
                name: 'primary',
                include: [/.*/],
                exclude: [/(\/(en|zh))*\/login/, /(\/(en|zh))*\/secondary\/(.*)/],
            },
            {
                name: 'secondary',
                include: [/(\/(en|zh))*\/secondary\/(.*)/],
            },
    ],
    
  2. src/layouts/BaseLayout.js 文件中新增 secondary 布局组件。

    import SecondaryLayout from './SecondaryLayout'
    
    const LayoutMap = {
      primary: PrimaryLayout,
      public: PublicLayout,
      secondary: SecondaryLayout,
    }
    
  3. src/layouts/ 目录中新增 SecondaryLayout.js 文件。

    import React from 'react'
    
    export default ({ children }) => {
      return (
        <div>
          <h1>Secondary</h1>
          {children}
        </div>
      )
    }
    
  4. src/pages/ 目录中新增 secondary/index.js 文件。

    import React from 'react'
    
    export default ({ children }) => {
      return <div>Secondary page Content</div>
    }
    
  5. 最后,启动开发模式 npm run start,打开 http://localhost:7000/secondary/,你将看到 secondary 布局的页面。

配置项

你可以在 /src/utils/config.js 里做一些自定义配置:

siteName

  • 类型: String

    配置站点名称,应用到登录框,侧边栏顶部的标题文字显示。

  • 类型: String

    配置版权声明,应用到登录页、Primay布局底部。

logoPath

  • 类型: String

    配置站点 Logo,应用到登录框,侧边栏顶部的 Logo 显示。

apiPrefix

  • 类型: String

    配置项目中接口的前缀,接口相关文档可查看 接口配置

fixedHeader

  • 类型: String

    Primary布局下,页面滚动时是否固定顶部。

layouts

  • 类型: Array

    配置哪些路由使用哪种布局,未指定路由使用默认布局 Public,项目中目前有 PrimaryPublic 两种布局, 默认配置如下:

        layouts: [
            {
                name: 'primary',
                include: [/.*/],
                exclude: [/(\/(en|zh))*\/login/],
            },
        ],
    

    每种布局的对象属性如下:

    • name - 布局的名称;

    • include - 指定使用该布局的路由规则列表,规则可为正则表达式或者字符串;

    • exclude - 指定不使用该布局的路由规则列表,规则可为正则表达式或者字符串。

注意:exclude 优先级高于 include,前面的布局优先级高于后面的布局。开发过程中可能需要结合src/layouts目录下的布局使用,具体方法可查看 使用布局

i18n

  • 类型: Object

    配置国际化,默认配置如下:

    i18n: {
        languages: [
          {
              key: 'en',
              title: 'English',
              flag: '/america.svg',
          },
          {
              key: 'zh',
              title: '中文',
              flag: '/china.svg',
          },
        ],
        defaultLanguage: 'en',
    }
    

    i18n.languages

    • 类型: Array

      指定应用支持哪些语言,每种语言的对象属性如下:

      • key - 语言的key,应用到页面 url 上以区分语言,也对应 src/locales 目录下的语言包文件夹名;

      • title - 语言名称,在登录页底部、Primay 布局顶部语言切换显示;

      • flag - 语言的国旗图标的路径,在 Primay 布局顶部语言切换显示。

i18n.defaultLanguage

  • 类型: String

    配置默认语言。

问题集锦

新建页面

1. 直接从/src/pages复制一个page (会自动创建路由[umi](https://umijs.org/zh/guide/router.html#%E7%BA%A6%E5%AE%9A%E5%BC%8F%E8%B7%AF%E7%94%B1))
2. 修改 namespace/pathToRegexp 在 task.js
3. 修改 mock中route.js增加一条route

快速上手

在开始之前,推荐先学习 ReactES2015+Antd Design , 了解 UmiJSDva ,并正确安装和配置了 Node.js v8 或以上 、Git。提前了解和学习这些知识会非常有帮助。

安装

git clone https://github.com/BinChengZhao/delicate.git my-project
cd my-project

目录结构

应用的目录结构如下

├── dist/               # 默认build输出目录
├── mock/               # Mock文件目录
├── public/             # 静态资源文件目录
├── src/                # 源码目录
│ ├── components/       # 组件目录
│ ├── e2e/              # e2e目录
│ ├── layouts/          # 布局目录
│ ├── locales/          # 国际化文件目录
│ ├── models/           # 数据模型目录
│ ├── pages/            # 页面组件目录
│ ├── services/         # 数据接口目录
│ │ ├── api.js          # 接口配置
│ │ └── index.js        # 接口输出
│ ├── themes/           # 项目样式目录
│ │ ├── default.less    # 样式变量
│ │ ├── index.less      # 全局样式
│ │ ├── mixin.less      # 样式函数
│ │ └── vars.less       # 样式变量及函数
│ ├── utils/            # 工具函数目录
│ │ ├── config.js       # 项目配置
│ │ ├── constant.js     # 静态常量
│ │ ├── index.js        # 工具函数
│ │ ├── request.js      # 异步请求函数(axios)
│ │ └── theme.js        # 项目需要在js中使用到样式变量
├── .editorconfig       # 编辑器配置
├── .env                # 环境变量
├── .eslintrc           # ESlint配置
├── .gitignore          # Git忽略文件配置
├── .prettierignore     # Prettier忽略文件配置
├── .prettierrc         # Prettier配置
├── .stylelintrc.json   # Stylelint配置
├── .travis.yml         # Travis配置
└── .umirc.js           # Umi配置
└──  package.json       # 项目信息

本地开发

  1. 进入目录安装依赖,国内用户推荐使用 cnpm 进行加速
yarn install

或者

npm install
  1. 启动本地服务器
npm run start
  1. 启动完成后打开浏览器访问 http://localhost:7000,如果需要更改启动端口,可在 .env 文件中配置。

接口配置

为什么

在使用了redux或者dva项目中,我们经常会写类似下面的service层的函数,使代码结构更清晰,但是很容易看出,我们会写很多相似的代码,在delicate-rs@5.0中,使用了更加简洁的配置方式实现了相同的功能。

export async function login(data) {
  return request({
    url: '/api/v1/user/login',
    method: 'post',
    data,
  })
}

配置和使用

src/services/api.js文件中,你会看到如下配置对象,对象的键用于调用时的函数名称,对象的值为请求的url,默认请求方式为GET,如果是其他请求方式对象的值的格式则为'method url'

export default {
  ...
  queryUser: '/user/:id',
  queryUserList: '/users',
  updateUser: 'Patch /user/:id',
  createUser: 'POST /user/:id',
  removeUser: 'DELETE /user/:id',
  removeUserList: 'POST /users/delete',
  ...
}

在其他文件中使用

import { queryUser } from 'api'

// 一般文件中
...
queryUser(option).then(data => console.log(data))
...

// model文件中
...
yield call(queryUser, option)
...

实现方式

参考src/services/index.js文件,对api配置进行遍历,每个属性都返回对应的封装后的request函数。

import request from 'utils/request'
import { apiPrefix } from 'utils/config'

import api from './api'

const gen = params => {
  let url = apiPrefix + params
  let method = 'GET'

  const paramsArray = params.split(' ')
  if (paramsArray.length === 2) {
    method = paramsArray[0]
    url = apiPrefix + paramsArray[1]
  }

  return function(data) {
    return request({
      url,
      data,
      method,
    })
  }
}

const APIFunction = {}
for (const key in api) {
  APIFunction[key] = gen(api[key])
}

module.exports = APIFunction

国际化

新增应用语言

以新增日语为例。

i18n

  1. 添加语言包本地文件,ja 为日语的语言代码,支持翻译的语言列表参考 有道智云,运行下面命令后会生成 src/locales/ja/messages.json 文件。

    npm run add-locale ja
    
  2. 提取代码中需要翻译的字段,即 <Trans>message</Trans>intl.formatMessage({ id: 'messagemessage 字段,运行下面命令后 `src/locales/ja/messages.json' }) 将会出现提取后的字段配置。

    npm run extract
    

    你将看到如下信息:

     Catalog statistics:
     ┌─────────────┬─────────────┬─────────┐
     │ Language    │ Total count │ Missing │
     ├─────────────┼─────────────┼─────────┤
     │ en (source) │     52      │    -    │
     │ ja          │     52      │   52    │
     │ zh          │     52      │    0    │
     └─────────────┴─────────────┴─────────┘
    
  3. 与此同时,我们在 src/utils/config.js 新增相关配置。

    {
        ...
        i18n: {
            languages: [
                ...
                {
                    key:'ja',
                    title: '日本語',
                    flag: '/japanese.svg',
                },
            ],
        },
    }
    

     路由相关效果,配置后 npm run start 重启后生效。

  4. 使用内置的命令进行自动翻译,在 src/locales/ja/messages.json 中将会看到翻译后的配置。

    npm run trans:only
    

    你将看到如下信息:

    start: en -> ja
    ...
    youdao: en -> ja: Unpublished -> 未発表
    youdao: en -> ja: Update -> 更新
    youdao: en -> ja: Update User -> ユーザーの更新
    youdao: en -> ja: Username -> 名
    ...
    All translations have been completed.
    

    npm run trans 将会依次执行 npm run extractnpm run trans:only

  5. 最后,可以在 src/locales/ja/messages.json 中对翻译不准确的的字段进行调整。启动开发模式 npm run start,打开 http://localhost:7000/ja/login,你将看到日语版本的应用。

HTTP请求

本项目使用了axios提供http请求服务,文件在src/utils/request.js

自定义Header

为了提供鉴权、修改cookie等服务,可以手动修改Header

axios.defaults.headers.common['Authorization'] = 'token'

或者

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  config.headers.token = window.localStorage.getItem('token');
  return config;
}, function (error) {
  return Promise.reject(error);
});

部署

完成开发并且在开发环境验证之后,就需要部署给我们的用户了。

i18n

构建

先执行下面的命令,

npm run build

几秒后,输出应该如下:

> delicate-rs@5.0.0-beta build /Users/delicate/delicate-web
> umi build

[21:13:17] webpack compiled in 43s 868ms
 DONE  Compiled successfully in 43877ms          21:13:17

File sizes after gzip:

  1.3 MB     dist/vendors.async.js
  308.21 KB  dist/umi.js
  45.49 KB   dist/vendors.chunk.css
  36.08 KB   dist/p__chart__highCharts__index.async.js
  33.53 KB   dist/p__user__index.async.js
  22.36 KB   dist/p__chart__ECharts__index.async.js
  4.21 KB    dist/p__dashboard__index.async.js
  4.06 KB    dist/umi.css
  ...

build 命令会打包所有的资源,包含 JavaScript, CSS, web fonts, images, html 等。你可以在 dist/ 目录下找到这些文件。

如果有使用 HashHistory 、 部署 html 到非根目录、静态化等需求,请查看Umi 部署

本地验证

发布之前,可以通过 serve 做本地验证,

$ yarn global add serve
$ serve ./dist

Serving!

- Local:            http://localhost:5000
- On Your Network:  http://{Your IP}:5000

Copied local address to clipboard!

访问 http://localhost:5000,正常情况下法应该是和 npm start 一致的(接口可能无法获取到正确数据)。

部署

接下来,我们可以把静态文件上传到服务器,如果使用 Nginx 作为 Web server,你可以在 ngnix.conf 中这样配置:

server
	{
		listen       80;
        # 指定可访问的域名
		server_name web.delicate-rs.com;
        # 编译后的文件存放的目录
		root  /home/www/delicate-web/dist;

        # 代理服务端接口,避免跨域
		location /api {
			 proxy_pass http://*.*.*.*:8090/api;
		}

        # 因为前端使用了BrowserHistory,所以将路由 fallback 到 index.html
		location / {
				index  index.html;
				try_files $uri $uri/ /index.html;
		}
	}

重启 Web server,访问 http://web.delicate-rs.com ,你将看到正确的页面。

nginx -s reload

类似的,如果你使用 Caddy 作为 Web server,你可以在 Caddyfile 中这样配置:

web.delicate-rs.com {
        gzip
        root /home/www/delicate-web/dist
        proxy /api http://localhost:7000

        rewrite {
                if {path} not_match ^/api
                to {path} {path}/ /
        }
}


web.delicate-rs.com/public {
        gzip
        root  /home/www/delicate-web/dist/static/public
}

5.0.0

优化

  • 尽量使用修饰器,简化代码编写,提高代码可读性。

  • API 配置化,简化获取数据方式。

  • utils 内文件拆分,各司其职。

  • 简化utils/request文件,不做特殊处理。

规范

  • 函数添加描述、参数、返回值等注释,含糊不清的代码增加注释,规范参考 Google JavaScript Style Guide

  • 语义化版本号,规范参加 语义化版本 2.0.0

  • 静态代码检查,统一代码风格,代码提交前将会使用 prettierstylelinteslint 规范代码。

  • Git 提交信息规范化,git-commit-emoji-cn

  • 基于 Umi 的约定式路由,无需再写路由配置文件。

  • 使用 React 16 新特性,如 FragmentContextPureComponent等。

功能

  • 支持国际化,源码中抽离翻译字段,按需加载语言包,自动在线翻译。

  • 支持按需引入 lodash 函数。

  • 支持多布局,可根据规则规定哪些路由使用哪种布局。

  • 支持 Antd Admin 在 Travis 上自动编译和部署。

  • 使用 Docsify 生成文档网站。

样式

  • 新增 Antd Admin 独立 Logo。

  • 重写整体布局组件,优化菜单、面包屑导航自动高亮,菜单自动展开等逻辑。

  • 移动端菜单更改为抽屉式。

其他

  • 废弃 IconFontSearchDataTable等组件,因为在 Antd 中有很好的支持和可替代的。