# 1. JS规范

## 1.1 命名规范

### 1.1.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>变/常量命名需要有明确意义，要让开发人员能够一眼知道这个变量想干什么

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
// 定义融合商城（多品类商城）
const multipleCategoriesMall // 正确

// 定义灰度功能（在es搜索灰度测试中）
const inESSearchTesting // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
// 定义融合商城（联合商城）
const isCombinedMall // 错误

// 定义灰度功能（灰度）
const isGray // 错误
```

## 1.2 变量定义

### 1.2.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>禁止使用 `var` 定义变量

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const theVariable = '123'; // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
var theVariable = '123'; // 错误
```

### 1.2.2 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>对于不做值修改的变量必须使用 `const`，`let` 只能定义可变变量

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const theVariable = '123'; // 正确

let theVariabled = '123'; // 正确
theVariabled = '444';
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
let theVariable = '123'; // 错误
```

### 1.2.3 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>常量定义必须使用 `const`且使用大写字母+下划线（常量值可以任意）

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const TEXT_ALIAS = 'ABC'; // 正确
const TEXT_ALIAS_LOWER = 'acd'; // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
let TEXT_ALIAS = 'ABC'; // 错误
const abc = 'ABC'; // 错误
```

### 1.2.4 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>变量定义只能使用驼峰命名

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const theVariable = 'ddd'; // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
const the_variable = 'ddd'; // 错误
```

## 1.3 字符操作

### 1.3.1 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 使用模板字符串代替字符串拼接

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```javascript
const str = `123${theVariable}`; // 推荐
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```javascript
const theVariable = 'acc';
const str = '123' + theVariable; // 不推荐
```

### 1.3.2 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>接口请求类型场景下禁用任何字符串拼接/模板字符串（无 restful 场景）

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { get, post } from '@/utils/newRequest';

window.fetch('/demeter/user/api/ep/list', { id: 123, data: 123 }); // 正确
post('/demeter/user/api/ep/list', { id: 123, data: 123 }); // 正确import { get, post } from '@/utils/newRequest';

window.fetch('/demeter/user/api/ep/list', { id: 123, data: 123 }); // 正确
post('/demeter/user/api/ep/list', { id: 123, data: 123 }); // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { get, post } from '@/utils/newRequest';

window.fetch(`/demeter/user/api/ep/list?id=${id}`, { data: 123 }); // 错误
post(`/demeter/user/api/ep/list/${id}`, { data: 123 }); // 错误

window.fetch('/demeter/user/api/ep/list?id=' + id, { data: 123 }); // 错误
post('/demeter/user/api/ep/list/' + id, { data: 123 }); // 错误
```

## 1.4 引用包使用

### 1.4.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>禁用 `@cot` 下的一切东西，包括不限于函数/组件/常量/变量

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { withLoading } from '@cot/core/lib/utils/dva'; // 错误
import { xxx } from '@cot/...'; // 错误
```

### 1.4.2 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 使用内部库 `@bingo/enum` 定义枚举

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```java
import { craeteEnum } form '@bingo/enum';

const ORDER_STATUS = createEnum({     // 推荐
    CREATE: '创建',
    PAYED: '支付',
    ...
});
const orderPayStatus = ORDER_STATUS.PAYED.key;
const orderPayTextStatus = ORDER_STATUS.PAYED.name;
const payedState = ORDER_STATUS.PAYED.equal(orderPayStatus);
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```javascript
const ORDER_STATUS = {     // 不推荐
    CREATE: 'CREATE',
    PAYED: 'PAYED',
    ...
}
const ORDER_STATUS_TEXT = {     // 不推荐
    CREATE: '创建',
    PAYED: '支付',
    ...
}
const orderPayStatus = ORDER_STATUS.PAYED;
const orderPayTextStatus = ORDER_STATUS_TEXT.PAYED;
// ------------------------------------------------------------------------------
const ORDER_STATUS = {     // 不推荐
    key: {
        CREATE: 'CREATE',
        PAYED: 'PAYED',
        ...
    },
    text: {
        CREATE: '创建',
        PAYED: '支付',
        ...
    }
}
const orderPayStatus = ORDER_STATUS.key.PAYED;
const orderPayTextStatus = ORDER_STATUS.text.PAYED;
```

## 1.5 信息完善

### 1.5.1 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 函数/方法/类添加基本注释

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```javascript
// 处理url search参数字符串，将其转换为key -> value对象
function urlSearchToObject = (str) => {    // 推荐
 // ...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```javascript
// 无注释
function urlSearchToObject = (str) => {    // 不推荐
 // ...
}
```

### 1.5.2 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 使用jsDoc完善请求接口的入参注释描述与返回值注释描述

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```javascript
import { post } from '@/utils/newRequest';

/**
 * @description 供应商六率报表查询
 * @param {Object} params - 查询参数
 * @param {string} params.startDate - 开始日期
 * @param {string} params.endDate - 结束日期
 * @param {string} params.purchaseStockId - 所属市场
 * @param {string} params.sellerId - 供应商
 * @returns {Promise<Object>} - 查询结果
 */
const getServerConfig = (params) => {    // 推荐
    post('/demeter/server/ep/list', params);
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```javascript
import { post } from '@/utils/newRequest';

const getServerConfig = (params) => {    // 不推荐
    post('/demeter/server/ep/list', params);
}
```

## 1.6 逻辑规范

### 1.6.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 冗余重复逻辑（逻辑大部分相同）需要单独拆分

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
...
const combinedMallUser = !!props.ucStore.info.combinedMall && props.combinedMallGrayUser; // 正确
const onInputChange = () => {
    if (combinedMallUser) ...
}
const clickSubmitBtn = () => {
    if (combinedMallUser) ...
}
useEffect(() => {
    if (combinedMallUser) ...
}, [])
...
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
...
const onInputChange = () => {
    if (!!props.ucStore.info.combinedMall && props.combinedMallGrayUser) ... // 错误
}
const clickSubmitBtn = () => {
    if (!!props.ucStore.info.combinedMall && props.combinedMallGrayUser) ...
}
useEffect(() => {
    if (!!props.ucStore.info.combinedMall && props.combinedMallGrayUser) ...
}, [])
...
```

### 1.6.2 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 单一判断用字符串常量化，判断值变更后逻辑都是可用的

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const ORDER_FINISHED_STATUS = 'finished';
const statusIsOver = result.status === ORDER_FINISHED_STATUS; // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
const statusIsOver = result.status === 'finished'; // 错误
```

### 1.6.3 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 从后端接收到的 Array 类型数据需要做一次空值判断

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { getUserStores } from './utils/server'

const stores = (await getUserStores({ id: storeId }) ?? []);    // 正确
// ------------------------------------------------------------------------------
const stores = await getUserStores({ id: storeId });
(stores ?? []).map(...)    // 正确
stores?.map(...)        // 正确
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { getUserStores } from './utils/server'

const stores = await getUserStores({ id: storeId });
stores.map(...)    // 错误
```

## 1.7 其他

### 1.7.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 禁止使用全局 eslint ignore 注释，只允许单行注释且需要写明原因

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
// 正确
// 由于compression-webpack-plugin只用于开发打包，不应用于实际项目代码，所以禁用该项eslint检查
// eslint-disable-next-line import/no-extraneous-dependencies
const CompressionPlugin = require('compression-webpack-plugin');

// TODO: 此处待优化，由于xxx原因造成性能不佳，逻辑晦涩
const formSubmit = (formValues) => {
    ...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
// 错误
/* eslint-disable global-require */
/* eslint-disable import/no-extraneous-dependencies */
....
```



# 2. React规范

## 2.1 命名规范

### 2.1.1 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 包含 jsx 代码的文件使用 `.jsx/.tsx` 命名文件名

<span style="color: rgb(46,161,33); background-color: inherit">[建议]</span>

```javascript
// .jsx
<App>
    <div>React jsx</div> // 推荐
</App>
```

<span style="color: rgb(216,57,49); background-color: inherit">[不建议]</span>

```javascript
// .js
<App>
    <div>React jsx</div> // 不推荐
</App>
```

### 2.1.2 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>React 组件必须使用首字母大写

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { PureComponent } from 'react';

class Acomp extends PureComponent { ... } // 正确
// ------------------------------------------------------------------------------
function Acomp(props) { // 正确
    return // jsx...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { PureComponent } from 'react';

class a extends PureComponent { ... } // 错误
// ------------------------------------------------------------------------------
function acomp(props) { // 错误
    return // jsx...
}
```

## 2.2 组件规范

### 2.2.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 使用 Function 组件，禁止使用 Class 组件

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { useEffect, useState } from 'react';
function Acomp(props) { // 推荐
    const [systemConfig, setSystemConfig] = useState({});
    useEffect(() => {
        ...
    }, [])
    return ...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { PureComponent, Component } from 'react';


class Acomp extends Component { // 错误
    ...
}

class Acomp extends PureComponent {  // 错误
    constructor(props) {
        super(props);
        this.state = {
            systemConfig: {}
        }
    }
    componentDidMount() {
        ...
    }
}
```

### 2.2.2 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>React Function组件中禁止对组件参数props做默认对象赋值

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
const defaultInfo = {};
const defaultInfos = []
function Acomp(props) {
    const { info = defaultInfo, infos = defaultInfos } = props; // 正确
    return // jsx...
}
// ------------------------------------------------------------------------------
function Acomp(props) {
    const { info, infos } = props; // 正确
    const useInfo = info ?? {};
    const useInfos = infos ?? [];
    return // jsx...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
function Acomp(props) {
    const { info = {}, infos = [] } = props; // 错误
    return // jsx...
}
```

### 2.2.3 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>React Function组件中禁止在条件判断中使用 hooks 方法

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { useState } from 'react';

function Acomp(props) {
    const { info } = props; // 错误
    const [loading, setLoading] = useState(false);
    const [data, setData] = useState(info); // 正确

    return // jsx...
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { useState } from 'react';

function Acomp(props) {
    const { info } = props; // 错误
    const [loading, setLoading] = useState(false);

    if (info) {
        const [data, setData] = useState(info); // 错误
    }
    return // jsx...
}
```

### 2.2.4 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>useEffect hooks 中禁止使用 async 函数

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { useEffect } from 'react';

function Acomp(props) {
    useEffect(() => { // 正确
        ...
    }, [])
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { useEffect } from 'react';

function Acomp(props) {
    useEffect(async () => { // 错误
        ...
    }, [])
}
```

### 2.2.5 <span style="color: rgb(216,57,49); background-color: inherit">[强制] </span>禁用 `antd/form` 组件做表单设计，使用内部表单工具 `@bingo/xform-react` 代替

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { Input } from 'antd';
import { form, FormItemLayout. FormItem } from '@bingo/xform-react';

function Acomp(props) {
    const formIns = useMemo(form, []); // 正确
    return (
        <FormItemLayout>
            <FormItem form={formIns} name='name'>
                <Input />
            </FormItem>
        </FormItemLayout>
    )
}

```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import { Form, Input } from 'antd';

function Acomp(props) {
    const { form } = props;
    return (
        <Form.Item>
            {form.getFieldDecorator('name')(<Input />)}
        </Form.Item>
    )
} 
Form.create()(Acomp); // 错误
```

### 2.2.6 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> Function 组件不要过大，适当拆解组件

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```javascript
import { useState } from 'react';

function AcompHeader = (props) => {
    const [a, setA] = useState(...);
    return ...
}
function AcompContent = (props) => {
    const [b, setB] = useState(...);
    const [c, setC] = useState(...);
    return ...
}
function AcompFooter = (props) => {
    const [d, setD] = useState(...);
    return ...
}
function Acomp(props) {    // 推荐
    const [e, setE] = useState(...);
    ...
    // < 500行代码
    return (
        <div>
            <AcompHeader />
            <AcompContent />
            <AcompFooter />
        </div>
    )
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```javascript
import { useState } from 'react';

function Acomp(props) {    // 不推荐
    const [a, setA] = useState(...);
    const [b, setB] = useState(...);
    const [c, setC] = useState(...);
    const [d, setD] = useState(...);
    ...
    // 单方法500行以上代码
    return (
        <div>
            ...
        </div>
    )
}
```

### 2.2.7 <span style="color: rgb(216,57,49); background-color: inherit">[强制 ]</span> 禁止使用 `@bg/table-v3` 实现form + table组合功能，使用 @bingo/xform-react + withAntdTable hooks 实现该功能

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```javascript
import { Form, form, useAntdTable } from "@bingo/xform-react";

const formConfig = () => [    // 正确
  {
    name: 'username',
    label: '用户名',
    rules: [validator.required()],
    valueInterceptor: (e) => e.target.value,
    render: <Input placeholder="请输入用户名" />,
    table: {
      render(username) {
        return `用户 - ${username}`
      }
    }
  },
  {
    table: {
      title: '年龄',
      dataIndex: 'age',
    }
  }
];
...
const formIns = useMemo(form, []);
const config = useMemo(formConfig, []);
const [control, FormTable] = useAntdTable(Table, {
    dataRequest: ({ current, pageSize, ...otherParams }) => query(requestParams);
});

<FormTable form={formIns} config={config} rowKey="id" scroll={{ x: 'max-content' }} />
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```javascript
import Table from '@bg/table-v3';

...
const tableProps = {    // 错误
    rowKey: 'id',
    search: false,
    scroll: { x: 'max-content' },
    columns: [
      ...colunms,
      {
        title: '操作',
        dataIndex: 'options',
        render(_, record) {
            ...
        },
      },
    ],
    request: () => query(requestParams),
  };
<Table {...tableProps} />
...
```



# 3. Vue规范





# 4. CSS/SCSS/SASS/LESS规范

## 4.1 命名规范

### 4.1.1 <span style="color: rgb(216,57,49); background-color: inherit">[强制]</span> 禁止使用驼峰命名

<span style="color: rgb(46,161,33); background-color: inherit">[正确]</span>

```scss
.text-color {     // 正确
  color: 'red';
}
.text_color {     // 正确
  color: 'red';
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[错误]</span>

```scss
.textColor {     // 错误
  color: 'red';
}
```

### 4.1.2 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 使用 '\_' 符号作为单词之间的连接（snake case）

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```scss
.text_color {     // 推荐
  color: 'red';
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```scss
.text-color {     // 不推荐
  color: 'red';
}
```

### 4.1.3 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 书写顺序，相关的属性声明应当归为一组，并按照下面的顺序排列：

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```scss
.production-item {
  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  
  /* Box-model */
  display: block;
  float: right;
  width: 100px;
  height: 100px;
  
  /* Typography */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  color: #333;
  text-align: center;
  
  /* Visual */
  background-color: #f5f5f5;
  border: 1px solid #e5e5e5;
  border-radius: 3px;
  
  /* Misc */
  opacity: 1;
  z-index: 1;}
```

## 4.2 颜色规范

### 4.2.1 <span style="color: rgb(36,91,219); background-color: inherit">[建议]</span> 在没有透明度要求时不要使用 `rgba` 表达颜色

<span style="color: rgb(46,161,33); background-color: inherit">[推荐]</span>

```scss
.color {
    color: #333234;    // 推荐
}
```

<span style="color: rgb(216,57,49); background-color: inherit">[不推荐]</span>

```scss
.color {
    color: rgba(12, 32, 44, 1);    // 不推荐
}
```

