diff --git a/doc/.gitignore b/doc/.gitignore index d46af7243..7c14f3874 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,3 +1,4 @@ node_modules .temp .cache +dist \ No newline at end of file diff --git a/doc/.vuepress/config.ts b/doc/.vuepress/config.ts index 080e6a9c3..630f8c6a4 100644 --- a/doc/.vuepress/config.ts +++ b/doc/.vuepress/config.ts @@ -22,6 +22,8 @@ export default defineUserConfig({ ['meta', { name: 'theme-color', content: '#3eaf7c' }], ], + pagePatterns: ['**/*.md', '!.vuepress', '!node_modules', '!old'], + plugins: [ searchPlugin({ // 配置项 diff --git a/doc/package.json b/doc/package.json index 19b045a37..acb39d1a1 100644 --- a/doc/package.json +++ b/doc/package.json @@ -10,7 +10,7 @@ "scripts": { "dev": "vuepress dev", "build:comment": "echo '构建帮助文档,默认base前缀为document,可根据部署需要进行相应调整'", - "build": "BASE=CodeAnalysis vuepress build -d ./dist" + "build": "BASE=${BASE:-CodeAnalysis} vuepress build -d ./dist" }, "devDependencies": { "@vuepress/plugin-search": "^2.0.0-beta.43", diff --git a/web/build-source.sh b/web/build-source.sh index fb511df99..8f3d0cbf7 100644 --- a/web/build-source.sh +++ b/web/build-source.sh @@ -23,47 +23,61 @@ BUILD_ZIP_PATH="${ROOT_PATH}/tca-deploy-source/build_zip/" function default_frontend() { dist=${2:-dist} status "开始构建 $1 ..." - GIT_REVISION=$GIT_REVISION yarn build --scope ${1} + GIT_REVISION=$GIT_REVISION yarn build --scope "${1}" status "构建完成,开始打包到 tca-deploy-source" - cd ${ROOT_PATH}/packages/${1}/${dist} - zip -r ${1}.zip * --exclude '*.map' --exclude 'stats.json' --exclude '*.txt' - mv ${1}.zip ${BUILD_ZIP_PATH} && cd ${ROOT_PATH} + cd "${ROOT_PATH}"/packages/"${1}"/"${dist}" + zip -r "${1}".zip ./* --exclude '*.map' --exclude 'stats.json' --exclude '*.txt' + mv "${1}".zip "${BUILD_ZIP_PATH}" && cd "${ROOT_PATH}" + status "打包完成 $1" +} + +# 文档构建资源打包 +function document_frontend() { + cd "${ROOT_PATH}" + cd "../doc" + status "开始构建 $1 ..." + yarn install && BASE=document yarn build + dist=${2:-dist} + status "构建完成,开始打包到 tca-deploy-source" + cd "${dist}" + zip -r "${1}".zip ./* --exclude '*.map' --exclude 'stats.json' --exclude '*.txt' + mv "${1}".zip "${BUILD_ZIP_PATH}" && cd "${ROOT_PATH}" status "打包完成 $1" } # 子微前端的构建资源打包 function sub_microfrontend() { status "开始构建 $1 ..." - GIT_REVISION=$GIT_REVISION PUBLIC_PATH=/static/$1/ ENABLE_EXTERNALS=TRUE yarn build --scope $1 + GIT_REVISION=$GIT_REVISION PUBLIC_PATH=/static/$1/ ENABLE_EXTERNALS=TRUE yarn build --scope "$1" status "构建完成,开始打包到 tca-deploy-source" - cd ${ROOT_PATH}/packages/${1}/dist - zip -r ${1}.zip * --exclude '*.map' --exclude 'stats.json' --exclude '*.txt' --exclude '*.html' - mv ${1}.zip ${BUILD_ZIP_PATH} && cd ${ROOT_PATH} + cd "${ROOT_PATH}"/packages/"${1}"/dist + zip -r "${1}".zip ./* --exclude '*.map' --exclude 'stats.json' --exclude '*.txt' --exclude '*.html' + mv "${1}".zip "${BUILD_ZIP_PATH}" && cd "${ROOT_PATH}" status "打包完成 $1" } function run() { BUILD_PKGS=("tca-document" "framework" "login" "tca-layout" "tca-analysis" "tca-manage") - for pkg_name in ${BUILD_PKGS[@]}; do + for pkg_name in "${BUILD_PKGS[@]}"; do if [ "$pkg_name" = "framework" ]; then - default_frontend $pkg_name + default_frontend "$pkg_name" elif [ "$pkg_name" = "tca-document" ]; then - default_frontend $pkg_name + document_frontend "$pkg_name" else - sub_microfrontend $pkg_name + sub_microfrontend "$pkg_name" fi done } function run_config() { - cd ${ROOT_PATH} + cd "${ROOT_PATH}" SUB_MICRO_FRONTEND_PKGS=("tca-layout" "login" "tca-analysis" "tca-manage") configs='' for i in "${!SUB_MICRO_FRONTEND_PKGS[@]}"; do pkg_name=${SUB_MICRO_FRONTEND_PKGS[$i]} - configs+=', '$(cat ${ROOT_PATH}/packages/${pkg_name}/dist/$pkg_name.json) + configs+=', '$(cat "${ROOT_PATH}"/packages/"${pkg_name}"/dist/"$pkg_name".json) done - echo '['${configs:2}']' >${CONF_PATH}/configs.json + echo '['"${configs:2}"']' >"${CONF_PATH}"/configs.json } run diff --git a/web/packages/login/README.md b/web/packages/login/README.md index 6e61723e2..a59d2f0f9 100644 --- a/web/packages/login/README.md +++ b/web/packages/login/README.md @@ -10,7 +10,7 @@ ## 本地启动脚本 ```bash -PUBLIC_PATH=http://127.0.0.1:5055/ yarn run dev +yarn run dev ``` ## 开发模式启动方式 @@ -18,10 +18,7 @@ PUBLIC_PATH=http://127.0.0.1:5055/ yarn run dev 使用如下命令启动: ```bash - xxx=xxx yarn run dev - - # 如 - PUBLIC_PATH=http://127.0.0.1:5055/ yarn run dev + yarn run dev ``` 启动后可通过以下进行开发: diff --git a/web/packages/shared/component/authority/constants.ts b/web/packages/shared/component/authority/constants.ts new file mode 100644 index 000000000..ec64a8b82 --- /dev/null +++ b/web/packages/shared/component/authority/constants.ts @@ -0,0 +1,42 @@ +/** 平台类型 */ +export enum ScmPlatformEnum { + TGIT = 1, + GIT_TENCENT, + CODING, + GITHUB, + GITEE, + GITLAB, + OTHER, +} + +export const SCM_PLATFORM_CHOICES = { + [ScmPlatformEnum.TGIT]: '腾讯工蜂(OA)', + [ScmPlatformEnum.GIT_TENCENT]: '腾讯工蜂', + [ScmPlatformEnum.CODING]: 'Coding', + [ScmPlatformEnum.GITHUB]: 'GitHub', + [ScmPlatformEnum.GITEE]: 'Gitee', + [ScmPlatformEnum.GITLAB]: 'GitLab', + [ScmPlatformEnum.OTHER]: '其它平台', +}; + +/** + * 凭证类型 + */ +export const AUTH_TYPE = { + HTTP: 'password', + SSH: 'ssh_token', + OAUTH: 'oauth', +}; + +export const AUTH_TYPE_TXT = { + HTTP: '用户名 + 密码', + SSH: 'SSH', + OAUTH: 'OAuth', +}; + +// 凭证映射,对应 api 返回的字段名 +export const SCM_MAP = { + [AUTH_TYPE.HTTP]: 'scm_account', + [AUTH_TYPE.SSH]: 'scm_ssh', + [AUTH_TYPE.OAUTH]: 'scm_oauth', +}; diff --git a/web/packages/tca-layout/src/components/authority/index.tsx b/web/packages/shared/component/authority/index.tsx similarity index 67% rename from web/packages/tca-layout/src/components/authority/index.tsx rename to web/packages/shared/component/authority/index.tsx index 0bb55d295..05f2fb72f 100644 --- a/web/packages/tca-layout/src/components/authority/index.tsx +++ b/web/packages/shared/component/authority/index.tsx @@ -2,34 +2,43 @@ * 选择认证 */ import React, { useState, useEffect } from 'react'; -import { find, isEmpty, get, filter } from 'lodash'; +import { find, isEmpty, filter, get } from 'lodash'; import { Button, Form, Select, Tooltip } from 'coding-oa-uikit'; import PlusIcon from 'coding-oa-uikit/lib/icon/Plus'; import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh'; -import { SCM_PLATFORM, AUTH_TYPE, AUTH_TYPE_TXT, SCM_MAP } from '@src/common/constants/authority'; -import { getSSHInfo, gScmAccounts as getScmAccounts, getOAuthInfo, getPlatformStatus } from '@src/services/user'; -import { FormInstance } from 'rc-field-form'; +import { AUTH_TYPE, AUTH_TYPE_TXT, SCM_MAP, SCM_PLATFORM_CHOICES } from './constants'; +import { FormInstance } from 'rc-field-form'; const { Option, OptGroup } = Select; +export interface RestfulListAPIParams { + results: any[]; + count: number; + next: string; + previous: string +} + interface AuthorityProps { - name: string; // 对应表单 name + name: string; // 对应表单 name form: FormInstance; // form 对象 label: string | React.ReactNode; // FormItem label + /* 接口顺序:获取ssh凭证,获取用户名密码凭证,获取各平台OAuth授权状态,获取各平台OAuth应用配置状态 **/ + getAuthList: Array<(param?: any) => Promise>; initAuth?: any; selectStyle?: any; placeholder?: string; + required?: boolean; } const Authority = (props: AuthorityProps) => { - const { form, name, label, initAuth, selectStyle = {}, placeholder } = props; + const { form, name, label, initAuth, getAuthList, selectStyle = {}, placeholder, required } = props; const [sshAuthList, setSshAuthList] = useState([]); const [httpAuthList, setHttpAuthList] = useState([]); const [oauthAuthList, setOauthAuthList] = useState([]); const [authLoading, setAuthLoading] = useState(false); - const setCurAuth = (sshList = sshAuthList, httpList = httpAuthList, oauthList = oauthAuthList) => { + const setCurAuth = (sshList = sshAuthList, httpList = httpAuthList) => { // 设置初始值 if (initAuth[SCM_MAP[initAuth.auth_type]]?.id) { form.setFieldsValue({ [name]: `${initAuth.auth_type}#${initAuth[SCM_MAP[initAuth.auth_type]]?.id}` }); @@ -50,29 +59,25 @@ const Authority = (props: AuthorityProps) => { ) { setHttpAuthList([initAuth.scm_account, ...httpList]); } - if ( - initAuth.scm_oauth - && initAuth.auth_type === AUTH_TYPE.OAUTH - && !find(oauthList, { id: initAuth.scm_oauth?.id }) - ) { - setOauthAuthList([initAuth.scm_oauth, ...oauthList]); - } }; const getAuth = () => { setAuthLoading(true); Promise.all([ - getSSHInfo().then(r => r.results || []), - getScmAccounts().then(r => r.results || []), - getOAuthInfo().then(r => r.results || []), - getPlatformStatus().then(r => r || []), - ]).then((result) => { + getAuthList[0]({ limit: 200 }) + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[1]({ limit: 200 }) + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[2]() + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[3]().then(r => r || {}), + ]).then((result: any) => { const activeOauth = filter( result[2].map((item: any) => ({ ...item, platform_status: get(result[3], item.scm_platform_name, [false]), })), - 'platform_status' + 'platform_status', ); setSshAuthList(result[0]); setHttpAuthList(result[1]); @@ -92,22 +97,23 @@ const Authority = (props: AuthorityProps) => { }, [initAuth, authLoading]); return ( - - - document.body} + optionLabelProp="label" > {!isEmpty(oauthAuthList) && ( {oauthAuthList.map((auth: any) => ( - // HTTP 和 SSH ID可能重复 ))} @@ -118,8 +124,10 @@ const Authority = (props: AuthorityProps) => { ))} @@ -130,8 +138,10 @@ const Authority = (props: AuthorityProps) => { ))} @@ -140,7 +150,7 @@ const Authority = (props: AuthorityProps) => {
document.body}> diff --git a/web/packages/shared/component/micro-init/index.tsx b/web/packages/shared/component/micro-init/index.tsx index a603cc1a4..3868c521c 100644 --- a/web/packages/shared/component/micro-init/index.tsx +++ b/web/packages/shared/component/micro-init/index.tsx @@ -4,10 +4,11 @@ import { legacy_createStore as createStore, combineReducers } from 'redux'; import { Provider } from 'react-redux'; import { ConfigProvider } from 'coding-oa-uikit'; import Cookie from 'universal-cookie'; -import 'coding-oa-uikit/dist/coding-oa-uikit.css'; +// import 'coding-oa-uikit/dist/coding-oa-uikit.css'; import { StoreProvider } from '../../hook-store'; import { Store, StateProps, ActionProps, Middleware } from '../../hook-store/types'; import '../../style/index.scss'; +import '../../style/zhiyan.css'; /** * 国际化资源加载 @@ -80,7 +81,7 @@ const MicroInit = (node ? node.parentNode as HTMLElement : document.body)} > {container} diff --git a/web/packages/tca-layout/src/components/delete-modal/index.tsx b/web/packages/shared/component/modal/delete-modal/index.tsx similarity index 84% rename from web/packages/tca-layout/src/components/delete-modal/index.tsx rename to web/packages/shared/component/modal/delete-modal/index.tsx index f2e3529a3..cf515005f 100644 --- a/web/packages/tca-layout/src/components/delete-modal/index.tsx +++ b/web/packages/shared/component/modal/delete-modal/index.tsx @@ -1,16 +1,10 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - /** * 确认删除操作弹框 */ import React, { useEffect, useState } from 'react'; import { Modal, Form, Input, message, Button } from 'coding-oa-uikit'; -import { t } from '@src/i18n/i18next'; +import { useTranslation } from 'react-i18next'; import s from './style.scss'; @@ -24,9 +18,10 @@ interface DeleteModalProps { onOk: () => void; } -const DeleteModal = ({ actionType, objectType, confirmName, addtionInfo='', visible, onCancel, onOk }: DeleteModalProps) => { +const DeleteModal = ({ actionType, objectType, confirmName, addtionInfo = '', visible, onCancel, onOk }: DeleteModalProps) => { const [form] = Form.useForm(); const [confirmed, setConfirmed] = useState(true); + const { t } = useTranslation(); useEffect(() => { visible && form.resetFields(); @@ -81,7 +76,7 @@ const DeleteModal = ({ actionType, objectType, confirmName, addtionInfo='', visi ]} >

- {t('您正在')}{actionType}{objectType} {confirmName}{' '}
+ {t('您正在')}{actionType}{objectType} {confirmName}{' '}

{addtionInfo &&

{addtionInfo}

}

{t(`为确认${actionType}操作,请输入您要${actionType}的`)}{objectType}

diff --git a/web/packages/tca-layout/src/components/delete-modal/style.scss b/web/packages/shared/component/modal/delete-modal/style.scss similarity index 100% rename from web/packages/tca-layout/src/components/delete-modal/style.scss rename to web/packages/shared/component/modal/delete-modal/style.scss diff --git a/web/packages/shared/component/node-status/index.tsx b/web/packages/shared/component/node-status/index.tsx new file mode 100644 index 000000000..7f6b61069 --- /dev/null +++ b/web/packages/shared/component/node-status/index.tsx @@ -0,0 +1,53 @@ +/** + * 节点状态组件 + */ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Tag } from 'coding-oa-uikit'; +import Loading from 'coding-oa-uikit/lib/icon/Loading'; +import Stop from 'coding-oa-uikit/lib/icon/Stop'; +import ExclamationCircle from 'coding-oa-uikit/lib/icon/ExclamationCircle'; +import DotCircle from 'coding-oa-uikit/lib/icon/DotCircle'; + +export enum StatusEnum { + /** 不可用 */ + DISACTIVE, + /** 活跃 */ + ACTIVE, + /** 离线 */ + OFFLINE, +} + +export enum StateEnum { + /** 空闲 */ + FREE, + /** 忙碌 */ + BUSY +} + +interface NodeStatusProps { + /** 节点信息 */ + node: any +} + +/** 节点状态组件 */ +const NodeStatus = ({ node }: NodeStatusProps) => { + const { t } = useTranslation(); + + if (node) { + const { enabled, state } = node; + if (enabled === StatusEnum.ACTIVE && state === StateEnum.BUSY) { + return } color='processing'>{t('运行中')}; + } + if (enabled === StatusEnum.ACTIVE) { + return } color='success'>{t('在线')}; + } + if (enabled === StatusEnum.DISACTIVE) { + return }>{t('失效')}; + } + return } color='warning'>{t('离线')}; + } + return <>; +}; + +export default NodeStatus; diff --git a/web/packages/shared/component/notification/useNotification.tsx b/web/packages/shared/component/notification/useNotification.tsx index 1454b30ff..78c85bb28 100644 --- a/web/packages/shared/component/notification/useNotification.tsx +++ b/web/packages/shared/component/notification/useNotification.tsx @@ -31,7 +31,7 @@ const setNotificationDataToLocalStorage = (key: string, notifyStorageData: Notif }; /** 通知入参数数据结构 */ -interface NotificationProps { +export interface NotificationProps { /** 唯一标识 */ key: string, /** 通知类型 */ diff --git a/web/packages/shared/i18n/index.ts b/web/packages/shared/i18n/index.ts index 973618ce0..de55eedae 100644 --- a/web/packages/shared/i18n/index.ts +++ b/web/packages/shared/i18n/index.ts @@ -10,6 +10,14 @@ export interface InitI18next { modules?: any[] } +/** 去除PUBLIC_PATH末尾斜杠 */ +const getPublicPath = (publicPath: string) => { + if (publicPath.endsWith('/')) { + return publicPath.substring(0, publicPath.length - 1); + } + return publicPath; +}; + /** * 初始化i18n * @param param0 {options, modules} 参数配置 @@ -27,6 +35,7 @@ const initI18next = ({ options, modules = [] }: InitI18next) => { react: { useSuspense: false, }, + load: 'currentOnly', fallbackLng: 'zh-CN', // 未找到最终匹配zh_CN interpolation: { escapeValue: false, @@ -35,6 +44,9 @@ const initI18next = ({ options, modules = [] }: InitI18next) => { // caches: ['localStorage', 'cookie'], caches: ['cookie'], }, + backend: { + loadPath: `${getPublicPath(process.env.PUBLIC_PATH)}/locales/{{lng}}/{{ns}}.json`, + }, ...options, }; diff --git a/web/packages/shared/style/zhiyan.css b/web/packages/shared/style/zhiyan.css new file mode 100644 index 000000000..326cb8123 --- /dev/null +++ b/web/packages/shared/style/zhiyan.css @@ -0,0 +1 @@ +html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;color:#000a29e6;font-size:14px;font-family:PingFang SC,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-variant:tabular-nums;line-height:1.5715;background-color:#fff;font-feature-settings:"tnum"}[tabindex="-1"]:focus{outline:none!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;color:#000a29e6;font-weight:500}p{margin-top:0;margin-bottom:0}abbr[title],abbr[data-original-title]{text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0052d9;text-decoration:none;background-color:transparent;outline:none;cursor:pointer;transition:color .3s;-webkit-text-decoration-skip:objects}a:hover{color:#2575e6}a:active{color:#003eb3}a:active,a:hover{text-decoration:none;outline:0}a:focus{text-decoration:none;outline:0}a[disabled]{color:#00000040;cursor:not-allowed;pointer-events:none}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}a,area,button,[role=button],input:not([type="range"]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;color:#000a2999;text-align:left;caption-side:bottom}th{text-align:inherit}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#fffbe5}.clearfix:before{display:table;content:""}.clearfix:after{display:table;clear:both;content:""}.cuk2-icon{font-size:16px}.anticon{display:inline-block;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.anticon>*{line-height:1}.anticon svg{display:inline-block}.anticon:before{display:none}.anticon .anticon-icon{display:block}.anticon[tabindex]{cursor:pointer}.anticon-spin:before{display:inline-block;animation:loadingCircle 1s infinite linear}.anticon-spin{display:inline-block;animation:loadingCircle 1s infinite linear}.fade-enter,.fade-appear,.fade-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.fade-enter.fade-enter-active,.fade-appear.fade-appear-active{animation-name:antFadeIn;animation-play-state:running}.fade-leave.fade-leave-active{animation-name:antFadeOut;animation-play-state:running;pointer-events:none}.fade-enter,.fade-appear{opacity:0;animation-timing-function:linear}.fade-leave{animation-timing-function:linear}@keyframes antFadeIn{0%{opacity:0}to{opacity:1}}@keyframes antFadeOut{0%{opacity:1}to{opacity:0}}.move-up-enter,.move-up-appear,.move-up-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.move-up-enter.move-up-enter-active,.move-up-appear.move-up-appear-active{animation-name:antMoveUpIn;animation-play-state:running}.move-up-leave.move-up-leave-active{animation-name:antMoveUpOut;animation-play-state:running;pointer-events:none}.move-up-enter,.move-up-appear{opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-up-leave{animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-down-enter,.move-down-appear,.move-down-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.move-down-enter.move-down-enter-active,.move-down-appear.move-down-appear-active{animation-name:antMoveDownIn;animation-play-state:running}.move-down-leave.move-down-leave-active{animation-name:antMoveDownOut;animation-play-state:running;pointer-events:none}.move-down-enter,.move-down-appear{opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-down-leave{animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-left-enter,.move-left-appear,.move-left-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.move-left-enter.move-left-enter-active,.move-left-appear.move-left-appear-active{animation-name:antMoveLeftIn;animation-play-state:running}.move-left-leave.move-left-leave-active{animation-name:antMoveLeftOut;animation-play-state:running;pointer-events:none}.move-left-enter,.move-left-appear{opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-left-leave{animation-timing-function:cubic-bezier(.6,.04,.98,.34)}.move-right-enter,.move-right-appear,.move-right-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.move-right-enter.move-right-enter-active,.move-right-appear.move-right-appear-active{animation-name:antMoveRightIn;animation-play-state:running}.move-right-leave.move-right-leave-active{animation-name:antMoveRightOut;animation-play-state:running;pointer-events:none}.move-right-enter,.move-right-appear{opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.move-right-leave{animation-timing-function:cubic-bezier(.6,.04,.98,.34)}@keyframes antMoveDownIn{0%{transform:translateY(100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@keyframes antMoveDownOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(100%);transform-origin:0 0;opacity:0}}@keyframes antMoveLeftIn{0%{transform:translate(-100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@keyframes antMoveLeftOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(-100%);transform-origin:0 0;opacity:0}}@keyframes antMoveRightIn{0%{transform:translate(100%);transform-origin:0 0;opacity:0}to{transform:translate(0);transform-origin:0 0;opacity:1}}@keyframes antMoveRightOut{0%{transform:translate(0);transform-origin:0 0;opacity:1}to{transform:translate(100%);transform-origin:0 0;opacity:0}}@keyframes antMoveUpIn{0%{transform:translateY(-100%);transform-origin:0 0;opacity:0}to{transform:translateY(0);transform-origin:0 0;opacity:1}}@keyframes antMoveUpOut{0%{transform:translateY(0);transform-origin:0 0;opacity:1}to{transform:translateY(-100%);transform-origin:0 0;opacity:0}}@keyframes loadingCircle{to{transform:rotate(360deg)}}[ant-click-animating=true],[ant-click-animating-without-extra-node=true]{position:relative}html{--antd-wave-shadow-color: #0052d9;--scroll-bar: 0}[ant-click-animating-without-extra-node=true]:after,.ant-click-animating-node{position:absolute;top:0;right:0;bottom:0;left:0;display:block;border-radius:inherit;box-shadow:0 0 #0052d9;box-shadow:0 0 0 0 var(--antd-wave-shadow-color);opacity:.2;animation:fadeEffect 2s cubic-bezier(.08,.82,.17,1),waveEffect .4s cubic-bezier(.08,.82,.17,1);animation-fill-mode:forwards;content:"";pointer-events:none}@keyframes waveEffect{to{box-shadow:0 0 #0052d9;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@keyframes fadeEffect{to{opacity:0}}.slide-up-enter,.slide-up-appear,.slide-up-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.slide-up-enter.slide-up-enter-active,.slide-up-appear.slide-up-appear-active{animation-name:antSlideUpIn;animation-play-state:running}.slide-up-leave.slide-up-leave-active{animation-name:antSlideUpOut;animation-play-state:running;pointer-events:none}.slide-up-enter,.slide-up-appear{opacity:0;animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-up-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-down-enter,.slide-down-appear,.slide-down-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.slide-down-enter.slide-down-enter-active,.slide-down-appear.slide-down-appear-active{animation-name:antSlideDownIn;animation-play-state:running}.slide-down-leave.slide-down-leave-active{animation-name:antSlideDownOut;animation-play-state:running;pointer-events:none}.slide-down-enter,.slide-down-appear{opacity:0;animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-down-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-left-enter,.slide-left-appear,.slide-left-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.slide-left-enter.slide-left-enter-active,.slide-left-appear.slide-left-appear-active{animation-name:antSlideLeftIn;animation-play-state:running}.slide-left-leave.slide-left-leave-active{animation-name:antSlideLeftOut;animation-play-state:running;pointer-events:none}.slide-left-enter,.slide-left-appear{opacity:0;animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-left-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}.slide-right-enter,.slide-right-appear,.slide-right-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.slide-right-enter.slide-right-enter-active,.slide-right-appear.slide-right-appear-active{animation-name:antSlideRightIn;animation-play-state:running}.slide-right-leave.slide-right-leave-active{animation-name:antSlideRightOut;animation-play-state:running;pointer-events:none}.slide-right-enter,.slide-right-appear{opacity:0;animation-timing-function:cubic-bezier(.23,1,.32,1)}.slide-right-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}@keyframes antSlideUpIn{0%{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@keyframes antSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}}@keyframes antSlideDownIn{0%{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}to{transform:scaleY(1);transform-origin:100% 100%;opacity:1}}@keyframes antSlideDownOut{0%{transform:scaleY(1);transform-origin:100% 100%;opacity:1}to{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}}@keyframes antSlideLeftIn{0%{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleX(1);transform-origin:0% 0%;opacity:1}}@keyframes antSlideLeftOut{0%{transform:scaleX(1);transform-origin:0% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:0% 0%;opacity:0}}@keyframes antSlideRightIn{0%{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}to{transform:scaleX(1);transform-origin:100% 0%;opacity:1}}@keyframes antSlideRightOut{0%{transform:scaleX(1);transform-origin:100% 0%;opacity:1}to{transform:scaleX(.8);transform-origin:100% 0%;opacity:0}}.zoom-enter,.zoom-appear,.zoom-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-enter.zoom-enter-active,.zoom-appear.zoom-appear-active{animation-name:antZoomIn;animation-play-state:running}.zoom-leave.zoom-leave-active{animation-name:antZoomOut;animation-play-state:running;pointer-events:none}.zoom-enter,.zoom-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-big-enter,.zoom-big-appear,.zoom-big-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-big-enter.zoom-big-enter-active,.zoom-big-appear.zoom-big-appear-active{animation-name:antZoomBigIn;animation-play-state:running}.zoom-big-leave.zoom-big-leave-active{animation-name:antZoomBigOut;animation-play-state:running;pointer-events:none}.zoom-big-enter,.zoom-big-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-big-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-big-fast-enter,.zoom-big-fast-appear,.zoom-big-fast-leave{animation-duration:.1s;animation-fill-mode:both;animation-play-state:paused}.zoom-big-fast-enter.zoom-big-fast-enter-active,.zoom-big-fast-appear.zoom-big-fast-appear-active{animation-name:antZoomBigIn;animation-play-state:running}.zoom-big-fast-leave.zoom-big-fast-leave-active{animation-name:antZoomBigOut;animation-play-state:running;pointer-events:none}.zoom-big-fast-enter,.zoom-big-fast-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-big-fast-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-up-enter,.zoom-up-appear,.zoom-up-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-up-enter.zoom-up-enter-active,.zoom-up-appear.zoom-up-appear-active{animation-name:antZoomUpIn;animation-play-state:running}.zoom-up-leave.zoom-up-leave-active{animation-name:antZoomUpOut;animation-play-state:running;pointer-events:none}.zoom-up-enter,.zoom-up-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-up-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-down-enter,.zoom-down-appear,.zoom-down-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-down-enter.zoom-down-enter-active,.zoom-down-appear.zoom-down-appear-active{animation-name:antZoomDownIn;animation-play-state:running}.zoom-down-leave.zoom-down-leave-active{animation-name:antZoomDownOut;animation-play-state:running;pointer-events:none}.zoom-down-enter,.zoom-down-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-down-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-left-enter,.zoom-left-appear,.zoom-left-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-left-enter.zoom-left-enter-active,.zoom-left-appear.zoom-left-appear-active{animation-name:antZoomLeftIn;animation-play-state:running}.zoom-left-leave.zoom-left-leave-active{animation-name:antZoomLeftOut;animation-play-state:running;pointer-events:none}.zoom-left-enter,.zoom-left-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-left-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}.zoom-right-enter,.zoom-right-appear,.zoom-right-leave{animation-duration:.2s;animation-fill-mode:both;animation-play-state:paused}.zoom-right-enter.zoom-right-enter-active,.zoom-right-appear.zoom-right-appear-active{animation-name:antZoomRightIn;animation-play-state:running}.zoom-right-leave.zoom-right-leave-active{animation-name:antZoomRightOut;animation-play-state:running;pointer-events:none}.zoom-right-enter,.zoom-right-appear{transform:scale(0);opacity:0;animation-timing-function:cubic-bezier(.08,.82,.17,1)}.zoom-right-leave{animation-timing-function:cubic-bezier(.78,.14,.15,.86)}@keyframes antZoomIn{0%{transform:scale(.2);opacity:0}to{transform:scale(1);opacity:1}}@keyframes antZoomOut{0%{transform:scale(1)}to{transform:scale(.2);opacity:0}}@keyframes antZoomBigIn{0%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@keyframes antZoomBigOut{0%{transform:scale(1)}to{transform:scale(.8);opacity:0}}@keyframes antZoomUpIn{0%{transform:scale(.8);transform-origin:50% 0%;opacity:0}to{transform:scale(1);transform-origin:50% 0%}}@keyframes antZoomUpOut{0%{transform:scale(1);transform-origin:50% 0%}to{transform:scale(.8);transform-origin:50% 0%;opacity:0}}@keyframes antZoomLeftIn{0%{transform:scale(.8);transform-origin:0% 50%;opacity:0}to{transform:scale(1);transform-origin:0% 50%}}@keyframes antZoomLeftOut{0%{transform:scale(1);transform-origin:0% 50%}to{transform:scale(.8);transform-origin:0% 50%;opacity:0}}@keyframes antZoomRightIn{0%{transform:scale(.8);transform-origin:100% 50%;opacity:0}to{transform:scale(1);transform-origin:100% 50%}}@keyframes antZoomRightOut{0%{transform:scale(1);transform-origin:100% 50%}to{transform:scale(.8);transform-origin:100% 50%;opacity:0}}@keyframes antZoomDownIn{0%{transform:scale(.8);transform-origin:50% 100%;opacity:0}to{transform:scale(1);transform-origin:50% 100%}}@keyframes antZoomDownOut{0%{transform:scale(1);transform-origin:50% 100%}to{transform:scale(.8);transform-origin:50% 100%;opacity:0}}.ant-motion-collapse-legacy{overflow:hidden}.ant-motion-collapse-legacy-active{transition:height .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1)!important}.ant-motion-collapse{overflow:hidden;transition:height .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1)!important}.ant-affix{position:fixed;z-index:10}.ant-alert{box-sizing:border-box;margin:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;padding:8px 15px 8px 38px;word-wrap:break-word;border-radius:3px}.ant-alert.ant-alert-no-icon{padding:8px 19px}.ant-alert.ant-alert-no-icon .ant-alert-close-icon{top:12.0005px}.ant-alert.ant-alert-closable{padding-right:30px}.ant-alert-icon{position:absolute;top:12.0005px;left:15px;font-size:16px}.ant-alert-description{display:none;font-size:12px;line-height:18px}.ant-alert-success{background-color:#bcebdc;border:1px solid #bcebdc}.ant-alert-success .ant-alert-icon{color:#00a870}.ant-alert-info{background-color:#d4e3fc;border:1px solid #d4e3fc}.ant-alert-info .ant-alert-icon{color:#0052d9}.ant-alert-warning{background-color:#f9e0c7;border:1px solid #f9e0c7}.ant-alert-warning .ant-alert-icon{color:#ed7b2f}.ant-alert-error{background-color:#f9d7d9;border:1px solid #f9d7d9}.ant-alert-error .ant-alert-icon{color:#e34d59}.ant-alert-error .ant-alert-description>pre{margin:0;padding:0}.ant-alert-close-icon{position:absolute;top:12.0005px;right:9px;padding:0;overflow:hidden;color:#8592a6;font-size:14px;line-height:14px;background-color:transparent;border:none;outline:none;cursor:pointer}.ant-alert-close-icon .anticon-close{color:#000a2999;transition:color .3s}.ant-alert-close-icon .anticon-close:hover{color:#000a29bf}.ant-alert-close-text{color:#000a2999;transition:color .3s}.ant-alert-close-text:hover{color:#000a29bf}.ant-alert-with-description{position:relative;padding:15px 15px 15px 63px;color:#606c80;line-height:1.5715;border-radius:3px}.ant-alert-with-description.ant-alert-no-icon{padding:15px 10px 15px 15px}.ant-alert-with-description .ant-alert-icon{position:absolute;left:15px}.ant-alert-with-description.ant-alert-grey-background{padding:10px 10px 10px 34px}.ant-alert-with-description.ant-alert-grey-background .ant-alert-icon{top:12px;left:12px}.ant-alert-with-description .ant-alert-close-icon{position:absolute;top:14px;right:9px;font-size:14px;cursor:pointer}.ant-alert-with-description.ant-alert-grey-background .ant-alert-close-icon{top:15px}.ant-alert-with-description .ant-alert-message{display:block;margin-bottom:4px;color:#000a29e6;font-size:14px;line-height:20px}.ant-alert-message{color:#000a29e6}.ant-alert-with-description .ant-alert-description{display:block}.ant-alert.ant-alert-closing{height:0!important;margin:0;padding-top:0;padding-bottom:0;transform-origin:50% 0;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-alert-slide-up-leave{animation:antAlertSlideUpOut .3s cubic-bezier(.78,.14,.15,.86);animation-fill-mode:both}.ant-alert-grey-background{padding-top:9px;padding-bottom:9px;background-color:#f5f7fa;border-top:none;border-right:1px solid #f5f7fa;border-bottom:none;border-radius:0}.ant-alert-grey-background.ant-alert-no-icon{padding-left:16px}.ant-alert-grey-background .ant-alert-icon{top:12px;left:12px}.ant-alert-grey-background.ant-alert-success{border-left:4px solid #7ad93a}.ant-alert-grey-background.ant-alert-info{border-left:4px solid #3d98ff}.ant-alert-grey-background.ant-alert-warning{border-left:4px solid #f9e0c7}.ant-alert-grey-background.ant-alert-error{border-left:4px solid #f76469}.ant-alert-banner{margin-bottom:0;border:0;border-radius:0}.ant-alert-banner.ant-alert-success{box-shadow:inset 0 -1px #7ad93a}.ant-alert-banner.ant-alert-info{box-shadow:inset 0 -1px #3d98ff}.ant-alert-banner.ant-alert-warning{box-shadow:inset 0 -1px #f9e0c7}.ant-alert-banner.ant-alert-error{box-shadow:inset 0 -1px #f76469}.ant-alert-no-background{background-color:transparent;border:0}@keyframes antAlertSlideUpIn{0%{transform:scaleY(0);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@keyframes antAlertSlideUpOut{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(0);transform-origin:0% 0%;opacity:0}}.ant-alert.ant-alert-rtl{padding:8px 37px 8px 15px;direction:rtl}.ant-alert-rtl.ant-alert.ant-alert-no-icon{padding:8px 15px}.ant-alert.ant-alert-rtl.ant-alert.ant-alert-closable{padding-right:37px;padding-left:30px}.ant-alert.ant-alert-rtl.ant-alert.ant-alert-no-icon.ant-alert-closable{padding-right:15px;padding-left:30px}.ant-alert-rtl .ant-alert-icon{right:16px;left:auto}.ant-alert-rtl .ant-alert-close-icon{right:auto;left:16px}.ant-alert.ant-alert-rtl.ant-alert-with-description,.ant-alert.ant-alert-rtl.ant-alert-with-description.ant-alert-closable{padding:15px 64px 15px 15px}.ant-alert.ant-alert-rtl.ant-alert-with-description.ant-alert-no-icon{padding:15px}.ant-alert-rtl.ant-alert-with-description .ant-alert-icon{right:24px;left:auto}.ant-alert-rtl.ant-alert-with-description .ant-alert-close-icon{right:auto;left:16px}.ant-anchor{box-sizing:border-box;margin:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;padding:0 0 0 2px}.ant-anchor-wrapper{margin-left:-4px;padding-left:4px;overflow:auto;background-color:#fff}.ant-anchor-ink{position:absolute;top:0;left:0;height:100%}.ant-anchor-ink:before{position:relative;display:block;width:2px;height:100%;margin:0 auto;background-color:#f0f0f0;content:" "}.ant-anchor-ink-ball{position:absolute;left:50%;display:none;width:8px;height:8px;background-color:#fff;border:2px solid #0052d9;border-radius:8px;transform:translate(-50%);transition:top .3s ease-in-out}.ant-anchor-ink-ball.visible{display:inline-block}.ant-anchor.fixed .ant-anchor-ink .ant-anchor-ink-ball{display:none}.ant-anchor-link{padding:7px 0 7px 16px;line-height:1.143}.ant-anchor-link-title{position:relative;display:block;margin-bottom:6px;overflow:hidden;color:#000a29e6;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-anchor-link-title:only-child{margin-bottom:0}.ant-anchor-link-active>.ant-anchor-link-title{color:#0052d9}.ant-anchor-link .ant-anchor-link{padding-top:5px;padding-bottom:5px}.ant-anchor-rtl{direction:rtl}.ant-anchor-rtl.ant-anchor-wrapper{margin-right:-4px;margin-left:0;padding-right:4px;padding-left:0}.ant-anchor-rtl .ant-anchor-ink{right:0;left:auto}.ant-anchor-rtl .ant-anchor-ink-ball{right:50%;left:0;transform:translate(50%)}.ant-anchor-rtl .ant-anchor-link{padding:7px 16px 7px 0}.ant-select-auto-complete{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum"}.ant-select-auto-complete .ant-select-clear{right:13px}.ant-avatar{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;overflow:hidden;color:#fff;white-space:nowrap;text-align:center;vertical-align:middle;background:#ccc;width:32px;height:32px;line-height:32px;border-radius:50%}.ant-avatar-image{background:#fff;border:1px solid rgba(32,45,64,.08)}.ant-avatar-string{position:absolute;left:50%;font-weight:500;font-size:18px;transform-origin:0 center}.ant-avatar.ant-avatar-icon{font-size:18px}.ant-avatar.ant-avatar-icon>.anticon{margin:0}.ant-avatar-lg{width:40px;height:40px;line-height:40px;border-radius:50%}.ant-avatar-lg-string{position:absolute;left:50%;font-weight:500;font-size:24px;transform-origin:0 center}.ant-avatar-lg.ant-avatar-icon{font-size:24px}.ant-avatar-lg.ant-avatar-icon>.anticon{margin:0}.ant-avatar-sm{width:24px;height:24px;line-height:24px;border-radius:50%}.ant-avatar-sm-string{position:absolute;left:50%;font-weight:500;font-size:14px;transform-origin:0 center}.ant-avatar-sm.ant-avatar-icon{font-size:14px}.ant-avatar-sm.ant-avatar-icon>.anticon{margin:0}.ant-avatar-square{border-radius:3px}.ant-avatar-square.ant-avatar-sm{line-height:24px}.ant-avatar .ant-avatar-delete{display:none}.ant-avatar:hover .ant-avatar-delete{position:absolute;display:block;width:100%;height:100%;background-color:#171d2680;border-radius:10px}.ant-avatar>img{display:block;width:100%;height:100%;object-fit:cover}.ant-avatar-group{display:inline-flex}.ant-avatar-group .ant-avatar{font-size:13px;box-shadow:-1.5px 0 #fff}.ant-avatar-group .ant-avatar:not(:first-child){margin-left:-6px}.ant-avatar-group .ant-avatar .ant-avatar-string{font-size:13px}.ant-avatar-group .ant-avatar-sm,.ant-avatar-group .ant-avatar-sm .ant-avatar-string{font-size:12px}.ant-avatar-group .ant-avatar-sm:not(:first-child){margin-left:-4px}.ant-avatar-group .ant-avatar-lg,.ant-avatar-group .ant-avatar-lg .ant-avatar-string{font-size:18px}.ant-avatar-group .ant-avatar-lg:not(:first-child){margin-left:-8px}.ant-avatar-group-popover .ant-avatar{margin-top:3px;margin-left:3px}.ant-avatar-group-rtl .ant-avatar:not(:first-child){margin-right:-6px;margin-left:0}.ant-avatar-group-popover.ant-popover-rtl .ant-avatar+.ant-avatar{margin-right:3px;margin-left:0}.ant-back-top{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:fixed;right:100px;bottom:50px;z-index:10;width:40px;height:40px;cursor:pointer}.ant-back-top-rtl{right:auto;left:100px;direction:rtl}.ant-back-top-content{width:40px;height:40px;overflow:hidden;color:#fff;text-align:center;background-color:#000a2999;border-radius:20px;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-back-top-content:hover{background-color:#000a29e6;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-back-top-icon{width:14px;height:16px;margin:12px auto;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC) 100%/100% no-repeat}@media screen and (max-width: 768px){.ant-back-top{right:60px}}@media screen and (max-width: 480px){.ant-back-top{right:20px}}.ant-badge{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;color:unset;line-height:1}.ant-badge-count{z-index:auto;min-width:20px;height:20px;padding:0 6px;color:#fff;font-weight:400;font-size:12px;line-height:20px;white-space:nowrap;text-align:center;background:#eb333f;border-radius:10px;box-shadow:0 0 0 1px #fff}.ant-badge-count a,.ant-badge-count a:hover{color:#fff}.ant-badge-count-sm{min-width:14px;height:14px;padding:0;font-size:12px;line-height:14px;border-radius:7px}.ant-badge-multiple-words{padding:0 8px}.ant-badge-dot{z-index:auto;width:6px;height:6px;background:#e34d59;border-radius:100%;box-shadow:0 0 0 1px #fff}.ant-badge-count,.ant-badge-dot,.ant-badge .ant-scroll-number-custom-component{position:absolute;top:0;right:0;transform:translate(50%,-50%);transform-origin:100% 0%}.ant-badge-status{line-height:inherit;vertical-align:baseline}.ant-badge-status-dot{position:relative;top:-1px;display:inline-block;width:6px;height:6px;vertical-align:middle;border-radius:50%}.ant-badge-status-success{background-color:#00a870}.ant-badge-status-processing{position:relative;background-color:#0052d9}.ant-badge-status-processing:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #0052d9;border-radius:50%;animation:antStatusProcessing 1.2s infinite ease-in-out;content:""}.ant-badge-status-default{background-color:#d9d9d9}.ant-badge-status-error{background-color:#e34d59}.ant-badge-status-warning{background-color:#f9e0c7}.ant-badge-status-pink,.ant-badge-status-magenta{background:#eb2f96}.ant-badge-status-red{background:#ca1628}.ant-badge-status-volcano{background:#fa541c}.ant-badge-status-orange{background:#cb6b0b}.ant-badge-status-yellow{background:#ce9c09}.ant-badge-status-gold{background:#faad14}.ant-badge-status-cyan{background:#0ba4bc}.ant-badge-status-lime{background:#a0d911}.ant-badge-status-green{background:#3ea00e}.ant-badge-status-blue{background:#0052cc}.ant-badge-status-geekblue{background:#2f54eb}.ant-badge-status-purple{background:#6812ca}.ant-badge-status-text{margin-left:8px;color:#000a29e6;font-size:14px}.ant-badge-zoom-appear,.ant-badge-zoom-enter{animation:antZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46);animation-fill-mode:both}.ant-badge-zoom-leave{animation:antZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6);animation-fill-mode:both}.ant-badge-not-a-wrapper:not(.ant-badge-status){vertical-align:middle}.ant-badge-not-a-wrapper .ant-scroll-number{position:relative;top:auto;display:block}@keyframes antStatusProcessing{0%{transform:scale(.8);opacity:.5}to{transform:scale(2.4);opacity:0}}.ant-scroll-number{overflow:hidden}.ant-scroll-number-only{display:inline-block;height:20px;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-scroll-number-only>p.ant-scroll-number-only-unit{height:20px;margin:0}.ant-scroll-number-symbol{vertical-align:top}@keyframes antZoomBadgeIn{0%{transform:scale(0) translate(50%,-50%);opacity:0}to{transform:scale(1) translate(50%,-50%)}}@keyframes antZoomBadgeOut{0%{transform:scale(1) translate(50%,-50%)}to{transform:scale(0) translate(50%,-50%);opacity:0}}.ant-ribbon-wrapper{position:relative}.ant-ribbon{box-sizing:border-box;margin:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:8px;height:22px;padding:0 8px;color:#fff;line-height:22px;white-space:nowrap;background-color:#0052d9;border-radius:3px}.ant-ribbon-text{color:#fff}.ant-ribbon-corner{position:absolute;top:100%;width:8px;height:8px;color:currentColor;border:4px solid;transform:scaleY(.75);transform-origin:top}.ant-ribbon-corner:after{position:absolute;top:-4px;left:-4px;width:inherit;height:inherit;color:#00000040;border:inherit;content:""}.ant-ribbon-color-pink,.ant-ribbon-color-magenta{color:#eb2f96;background:#eb2f96}.ant-ribbon-color-red{color:#ca1628;background:#ca1628}.ant-ribbon-color-volcano{color:#fa541c;background:#fa541c}.ant-ribbon-color-orange{color:#cb6b0b;background:#cb6b0b}.ant-ribbon-color-yellow{color:#ce9c09;background:#ce9c09}.ant-ribbon-color-gold{color:#faad14;background:#faad14}.ant-ribbon-color-cyan{color:#0ba4bc;background:#0ba4bc}.ant-ribbon-color-lime{color:#a0d911;background:#a0d911}.ant-ribbon-color-green{color:#3ea00e;background:#3ea00e}.ant-ribbon-color-blue{color:#0052cc;background:#0052cc}.ant-ribbon-color-geekblue{color:#2f54eb;background:#2f54eb}.ant-ribbon-color-purple{color:#6812ca;background:#6812ca}.ant-ribbon.ant-ribbon-placement-end{right:-8px;border-bottom-right-radius:0}.ant-ribbon.ant-ribbon-placement-end .ant-ribbon-corner{right:0;border-color:currentColor transparent transparent currentColor}.ant-ribbon.ant-ribbon-placement-start{left:-8px;border-bottom-left-radius:0}.ant-ribbon.ant-ribbon-placement-start .ant-ribbon-corner{left:0;border-color:currentColor currentColor transparent transparent}.ant-badge-rtl{direction:rtl}.ant-badge-rtl .ant-badge-count,.ant-badge-rtl .ant-badge-dot,.ant-badge-rtl .ant-badge .ant-scroll-number-custom-component{right:auto;left:0;direction:ltr;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl.ant-badge .ant-scroll-number-custom-component{right:auto;left:0;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl .ant-badge-status-text{margin-right:8px;margin-left:0}.ant-badge-rtl .ant-badge-zoom-appear,.ant-badge-rtl .ant-badge-zoom-enter{animation-name:antZoomBadgeInRtl}.ant-badge-rtl .ant-badge-zoom-leave{animation-name:antZoomBadgeOutRtl}.ant-badge-not-a-wrapper .ant-badge-count{transform:none}.ant-ribbon-rtl{direction:rtl}.ant-ribbon-rtl.ant-ribbon-placement-end{right:unset;left:-8px;border-bottom-right-radius:3px;border-bottom-left-radius:0}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner{right:unset;left:0;border-color:currentColor currentColor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner:after{border-color:currentColor currentColor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-start{right:-8px;left:unset;border-bottom-right-radius:0;border-bottom-left-radius:3px}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner{right:0;left:unset;border-color:currentColor transparent transparent currentColor}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner:after{border-color:currentColor transparent transparent currentColor}@keyframes antZoomBadgeInRtl{0%{transform:scale(0) translate(-50%,-50%);opacity:0}to{transform:scale(1) translate(-50%,-50%)}}@keyframes antZoomBadgeOutRtl{0%{transform:scale(1) translate(-50%,-50%)}to{transform:scale(0) translate(-50%,-50%);opacity:0}}.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";color:#000a2999;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#000a2999;transition:color .3s}.ant-breadcrumb a:hover{color:#2575e6}.ant-breadcrumb>span:last-child{color:#000a29e6}.ant-breadcrumb>span:last-child a{color:#000a29e6}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#000a2999}.ant-breadcrumb-link>.anticon+span{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before{display:table;content:""}.ant-breadcrumb-rtl:after{display:table;clear:both;content:""}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.ant-btn{line-height:1.5715;position:relative;display:inline-block;font-weight:400;white-space:nowrap;text-align:center;background-image:none;border:1px solid transparent;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);user-select:none;touch-action:manipulation;height:32px;padding:4px 15px;font-size:14px;border-radius:3px;color:#000a29e6;background-color:#fff;border-color:#d9d9d9}.ant-btn>.anticon{line-height:1}.ant-btn,.ant-btn:active,.ant-btn:focus{outline:0}.ant-btn:not([disabled]):hover{text-decoration:none}.ant-btn:not([disabled]):active{outline:0;box-shadow:none}.ant-btn.disabled,.ant-btn[disabled]{cursor:not-allowed}.ant-btn.disabled>*,.ant-btn[disabled]>*{pointer-events:none}.ant-btn-lg{height:40px;padding:6.4px 15px;font-size:16px;border-radius:3px}.ant-btn-md{height:32px;padding:4px 15px;font-size:14px;border-radius:3px}.ant-btn-sm{height:24px;padding:0 7px;font-size:14px;border-radius:3px}.ant-btn>a:only-child{color:currentColor}.ant-btn>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn:hover,.ant-btn:active,.ant-btn.active{color:#003eb3;background-color:#fff;border-color:#003eb3}.ant-btn:hover>a:only-child,.ant-btn:active>a:only-child,.ant-btn.active>a:only-child{color:currentColor}.ant-btn:hover>a:only-child:after,.ant-btn:active>a:only-child:after,.ant-btn.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-disabled,.ant-btn.disabled,.ant-btn[disabled],.ant-btn-disabled:hover,.ant-btn.disabled:hover,.ant-btn[disabled]:hover,.ant-btn-disabled:focus,.ant-btn.disabled:focus,.ant-btn[disabled]:focus,.ant-btn-disabled:active,.ant-btn.disabled:active,.ant-btn[disabled]:active,.ant-btn-disabled.active,.ant-btn.disabled.active,.ant-btn[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn:hover,.ant-btn.active{text-decoration:none;background:#f5f7fa;border-color:#dadfe6}.ant-btn>span{display:inline-block}.ant-btn-primary{color:#fff;background-color:#0052d9;border-color:#0052d9;text-shadow:0 -1px 0 rgba(0,0,0,.12)}.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-primary:hover,.ant-btn-primary:active,.ant-btn-primary.active{color:#fff;background-color:#003eb3;border-color:#003eb3}.ant-btn-primary:hover>a:only-child,.ant-btn-primary:active>a:only-child,.ant-btn-primary.active>a:only-child{color:currentColor}.ant-btn-primary:hover>a:only-child:after,.ant-btn-primary:active>a:only-child:after,.ant-btn-primary.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-primary-disabled,.ant-btn-primary.disabled,.ant-btn-primary[disabled],.ant-btn-primary-disabled:hover,.ant-btn-primary.disabled:hover,.ant-btn-primary[disabled]:hover,.ant-btn-primary-disabled:focus,.ant-btn-primary.disabled:focus,.ant-btn-primary[disabled]:focus,.ant-btn-primary-disabled:active,.ant-btn-primary.disabled:active,.ant-btn-primary[disabled]:active,.ant-btn-primary-disabled.active,.ant-btn-primary.disabled.active,.ant-btn-primary[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-primary:hover,.ant-btn-primary.active{text-decoration:none}.ant-btn-group .ant-btn-primary:not(:first-child):not(:last-child){border-right-color:#2575e6;border-left-color:#2575e6}.ant-btn-group .ant-btn-primary:not(:first-child):not(:last-child):disabled{border-color:#d9d9d9}.ant-btn-group .ant-btn-primary:first-child:not(:last-child){border-right-color:#2575e6}.ant-btn-group .ant-btn-primary:first-child:not(:last-child)[disabled]{border-right-color:#d9d9d9}.ant-btn-group .ant-btn-primary:last-child:not(:first-child),.ant-btn-group .ant-btn-primary+.ant-btn-primary{border-left-color:#2575e6}.ant-btn-group .ant-btn-primary:last-child:not(:first-child)[disabled],.ant-btn-group .ant-btn-primary+.ant-btn-primary[disabled]{border-left-color:#d9d9d9}.ant-btn-secondary{color:#202d40;background-color:#e6e9ed;border-color:#e6e9ed;text-shadow:0 -1px 0 rgba(0,0,0,.12);text-shadow:none}.ant-btn-secondary>a:only-child{color:currentColor}.ant-btn-secondary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-secondary:hover,.ant-btn-secondary:active,.ant-btn-secondary.active{color:#202d40;background-color:#b7bdc7;border-color:#b7bdc7}.ant-btn-secondary:hover>a:only-child,.ant-btn-secondary:active>a:only-child,.ant-btn-secondary.active>a:only-child{color:currentColor}.ant-btn-secondary:hover>a:only-child:after,.ant-btn-secondary:active>a:only-child:after,.ant-btn-secondary.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-secondary-disabled,.ant-btn-secondary.disabled,.ant-btn-secondary[disabled],.ant-btn-secondary-disabled:hover,.ant-btn-secondary.disabled:hover,.ant-btn-secondary[disabled]:hover,.ant-btn-secondary-disabled:focus,.ant-btn-secondary.disabled:focus,.ant-btn-secondary[disabled]:focus,.ant-btn-secondary-disabled:active,.ant-btn-secondary.disabled:active,.ant-btn-secondary[disabled]:active,.ant-btn-secondary-disabled.active,.ant-btn-secondary.disabled.active,.ant-btn-secondary[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-secondary:hover,.ant-btn-secondary.active{text-decoration:none;background:#e6e9ed;border-color:#e6e9ed;opacity:.8}.ant-btn-text{height:20px;padding:0;line-height:20px;color:#606c80;background-color:transparent;border-color:transparent;box-shadow:none}.ant-btn-text>a:only-child{color:currentColor}.ant-btn-text>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-text:hover,.ant-btn-text:active,.ant-btn-text.active{color:#003eb3;background-color:transparent;border-color:#003eb3}.ant-btn-text:hover>a:only-child,.ant-btn-text:active>a:only-child,.ant-btn-text.active>a:only-child{color:currentColor}.ant-btn-text:hover>a:only-child:after,.ant-btn-text:active>a:only-child:after,.ant-btn-text.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-text:hover{border-color:transparent}.ant-btn-text.active{color:#606c80;text-decoration:none;background-color:#e6e9ed;border-color:transparent;opacity:.8}.ant-btn-text-disabled,.ant-btn-text.disabled,.ant-btn-text[disabled],.ant-btn-text-disabled:hover,.ant-btn-text.disabled:hover,.ant-btn-text[disabled]:hover,.ant-btn-text-disabled:focus,.ant-btn-text.disabled:focus,.ant-btn-text[disabled]:focus,.ant-btn-text-disabled:active,.ant-btn-text.disabled:active,.ant-btn-text[disabled]:active,.ant-btn-text-disabled.active,.ant-btn-text.disabled.active,.ant-btn-text[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-text.ant-btn-lg{height:22px;line-height:22px}.ant-btn-text.ant-btn-sm{height:17px;line-height:17px}.ant-btn-ghost{color:#000a29e6;background-color:transparent;border-color:#d9d9d9}.ant-btn-ghost>a:only-child{color:currentColor}.ant-btn-ghost>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-ghost:hover,.ant-btn-ghost:active,.ant-btn-ghost.active{color:#003eb3;background-color:transparent;border-color:#003eb3}.ant-btn-ghost:hover>a:only-child,.ant-btn-ghost:active>a:only-child,.ant-btn-ghost.active>a:only-child{color:currentColor}.ant-btn-ghost:hover>a:only-child:after,.ant-btn-ghost:active>a:only-child:after,.ant-btn-ghost.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-ghost-disabled,.ant-btn-ghost.disabled,.ant-btn-ghost[disabled],.ant-btn-ghost-disabled:hover,.ant-btn-ghost.disabled:hover,.ant-btn-ghost[disabled]:hover,.ant-btn-ghost-disabled:focus,.ant-btn-ghost.disabled:focus,.ant-btn-ghost[disabled]:focus,.ant-btn-ghost-disabled:active,.ant-btn-ghost.disabled:active,.ant-btn-ghost[disabled]:active,.ant-btn-ghost-disabled.active,.ant-btn-ghost.disabled.active,.ant-btn-ghost[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-dashed{color:#000a29e6;background-color:#fff;border-color:#d9d9d9;border-style:dashed}.ant-btn-dashed>a:only-child{color:currentColor}.ant-btn-dashed>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dashed:hover,.ant-btn-dashed:active,.ant-btn-dashed.active{color:#003eb3;background-color:#fff;border-color:#003eb3}.ant-btn-dashed:hover>a:only-child,.ant-btn-dashed:active>a:only-child,.ant-btn-dashed.active>a:only-child{color:currentColor}.ant-btn-dashed:hover>a:only-child:after,.ant-btn-dashed:active>a:only-child:after,.ant-btn-dashed.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dashed-disabled,.ant-btn-dashed.disabled,.ant-btn-dashed[disabled],.ant-btn-dashed-disabled:hover,.ant-btn-dashed.disabled:hover,.ant-btn-dashed[disabled]:hover,.ant-btn-dashed-disabled:focus,.ant-btn-dashed.disabled:focus,.ant-btn-dashed[disabled]:focus,.ant-btn-dashed-disabled:active,.ant-btn-dashed.disabled:active,.ant-btn-dashed[disabled]:active,.ant-btn-dashed-disabled.active,.ant-btn-dashed.disabled.active,.ant-btn-dashed[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-danger{color:#fff;background-color:#e34d59;border-color:#e34d59;text-shadow:0 -1px 0 rgba(0,0,0,.12)}.ant-btn-danger>a:only-child{color:currentColor}.ant-btn-danger>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-danger:hover,.ant-btn-danger:active,.ant-btn-danger.active{color:#fff;background-color:#bd3746;border-color:#bd3746}.ant-btn-danger:hover>a:only-child,.ant-btn-danger:active>a:only-child,.ant-btn-danger.active>a:only-child{color:currentColor}.ant-btn-danger:hover>a:only-child:after,.ant-btn-danger:active>a:only-child:after,.ant-btn-danger.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-danger-disabled,.ant-btn-danger.disabled,.ant-btn-danger[disabled],.ant-btn-danger-disabled:hover,.ant-btn-danger.disabled:hover,.ant-btn-danger[disabled]:hover,.ant-btn-danger-disabled:focus,.ant-btn-danger.disabled:focus,.ant-btn-danger[disabled]:focus,.ant-btn-danger-disabled:active,.ant-btn-danger.disabled:active,.ant-btn-danger[disabled]:active,.ant-btn-danger-disabled.active,.ant-btn-danger.disabled.active,.ant-btn-danger[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-danger:hover,.ant-btn-danger.active{text-decoration:none;background:#f76469;border-color:#f76469}.ant-btn-link{height:20px;padding:0;line-height:20px;color:#0052d9;background-color:transparent;border-color:transparent;box-shadow:none}.ant-btn-link>a:only-child{color:currentColor}.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-link:hover,.ant-btn-link:active,.ant-btn-link.active{color:#003eb3;background-color:transparent;border-color:#003eb3}.ant-btn-link:hover>a:only-child,.ant-btn-link:active>a:only-child,.ant-btn-link.active>a:only-child{color:currentColor}.ant-btn-link:hover>a:only-child:after,.ant-btn-link:active>a:only-child:after,.ant-btn-link.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-link:hover,.ant-btn-link:active{color:#3d98ff;border-color:transparent}.ant-btn-link-disabled,.ant-btn-link.disabled,.ant-btn-link[disabled],.ant-btn-link-disabled:hover,.ant-btn-link.disabled:hover,.ant-btn-link[disabled]:hover,.ant-btn-link-disabled:focus,.ant-btn-link.disabled:focus,.ant-btn-link[disabled]:focus,.ant-btn-link-disabled:active,.ant-btn-link.disabled:active,.ant-btn-link[disabled]:active,.ant-btn-link-disabled.active,.ant-btn-link.disabled.active,.ant-btn-link[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-link.ant-btn-lg{height:22px;line-height:22px}.ant-btn-link.ant-btn-sm{height:17px;line-height:17px}.ant-btn-dangerous{color:#e34d59;background-color:#fff;border-color:#e34d59}.ant-btn-dangerous>a:only-child{color:currentColor}.ant-btn-dangerous>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous:hover,.ant-btn-dangerous:focus{color:#f0787e;background-color:#fff;border-color:#f0787e}.ant-btn-dangerous:hover>a:only-child,.ant-btn-dangerous:focus>a:only-child{color:currentColor}.ant-btn-dangerous:hover>a:only-child:after,.ant-btn-dangerous:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous:active,.ant-btn-dangerous.active{color:#bd3746;background-color:#fff;border-color:#bd3746}.ant-btn-dangerous:active>a:only-child,.ant-btn-dangerous.active>a:only-child{color:currentColor}.ant-btn-dangerous:active>a:only-child:after,.ant-btn-dangerous.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous-disabled,.ant-btn-dangerous.disabled,.ant-btn-dangerous[disabled],.ant-btn-dangerous-disabled:hover,.ant-btn-dangerous.disabled:hover,.ant-btn-dangerous[disabled]:hover,.ant-btn-dangerous-disabled:focus,.ant-btn-dangerous.disabled:focus,.ant-btn-dangerous[disabled]:focus,.ant-btn-dangerous-disabled:active,.ant-btn-dangerous.disabled:active,.ant-btn-dangerous[disabled]:active,.ant-btn-dangerous-disabled.active,.ant-btn-dangerous.disabled.active,.ant-btn-dangerous[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-dangerous.ant-btn-primary{color:#fff;background-color:#e34d59;border-color:#e34d59;text-shadow:0 -1px 0 rgba(0,0,0,.12)}.ant-btn-dangerous.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-primary:hover,.ant-btn-dangerous.ant-btn-primary:active,.ant-btn-dangerous.ant-btn-primary.active{color:#fff;background-color:#bd3746;border-color:#bd3746}.ant-btn-dangerous.ant-btn-primary:hover>a:only-child,.ant-btn-dangerous.ant-btn-primary:active>a:only-child,.ant-btn-dangerous.ant-btn-primary.active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-primary:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-primary:active>a:only-child:after,.ant-btn-dangerous.ant-btn-primary.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-primary-disabled,.ant-btn-dangerous.ant-btn-primary.disabled,.ant-btn-dangerous.ant-btn-primary[disabled],.ant-btn-dangerous.ant-btn-primary-disabled:hover,.ant-btn-dangerous.ant-btn-primary.disabled:hover,.ant-btn-dangerous.ant-btn-primary[disabled]:hover,.ant-btn-dangerous.ant-btn-primary-disabled:focus,.ant-btn-dangerous.ant-btn-primary.disabled:focus,.ant-btn-dangerous.ant-btn-primary[disabled]:focus,.ant-btn-dangerous.ant-btn-primary-disabled:active,.ant-btn-dangerous.ant-btn-primary.disabled:active,.ant-btn-dangerous.ant-btn-primary[disabled]:active,.ant-btn-dangerous.ant-btn-primary-disabled.active,.ant-btn-dangerous.ant-btn-primary.disabled.active,.ant-btn-dangerous.ant-btn-primary[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-dangerous.ant-btn-primary:hover,.ant-btn-dangerous.ant-btn-primary.active{text-decoration:none;background:#f76469;border-color:#f76469}.ant-btn-dangerous.ant-btn-link{color:#e34d59;background-color:transparent;border-color:transparent;box-shadow:none}.ant-btn-dangerous.ant-btn-link>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-dangerous.ant-btn-link:active,.ant-btn-dangerous.ant-btn-link.active{color:#003eb3;background-color:transparent;border-color:#003eb3}.ant-btn-dangerous.ant-btn-link:hover>a:only-child,.ant-btn-dangerous.ant-btn-link:active>a:only-child,.ant-btn-dangerous.ant-btn-link.active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-link:active>a:only-child:after,.ant-btn-dangerous.ant-btn-link.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-dangerous.ant-btn-link:focus{color:#f0787e;background-color:transparent;border-color:transparent}.ant-btn-dangerous.ant-btn-link:hover>a:only-child,.ant-btn-dangerous.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link:hover>a:only-child:after,.ant-btn-dangerous.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-link:active{color:#bd3746;background-color:transparent;border-color:transparent}.ant-btn-dangerous.ant-btn-link:active>a:only-child{color:currentColor}.ant-btn-dangerous.ant-btn-link:active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-dangerous.ant-btn-link-disabled,.ant-btn-dangerous.ant-btn-link.disabled,.ant-btn-dangerous.ant-btn-link[disabled],.ant-btn-dangerous.ant-btn-link-disabled:hover,.ant-btn-dangerous.ant-btn-link.disabled:hover,.ant-btn-dangerous.ant-btn-link[disabled]:hover,.ant-btn-dangerous.ant-btn-link-disabled:focus,.ant-btn-dangerous.ant-btn-link.disabled:focus,.ant-btn-dangerous.ant-btn-link[disabled]:focus,.ant-btn-dangerous.ant-btn-link-disabled:active,.ant-btn-dangerous.ant-btn-link.disabled:active,.ant-btn-dangerous.ant-btn-link[disabled]:active,.ant-btn-dangerous.ant-btn-link-disabled.active,.ant-btn-dangerous.ant-btn-link.disabled.active,.ant-btn-dangerous.ant-btn-link[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-icon-only{width:32px;height:32px;padding:2.4px 0;font-size:16px;border-radius:3px;vertical-align:-.5px}.ant-btn-icon-only>*{font-size:16px}.ant-btn-icon-only.ant-btn-lg{width:40px;height:40px;padding:4.9px 0;font-size:18px;border-radius:3px}.ant-btn-icon-only.ant-btn-lg>*{font-size:18px}.ant-btn-icon-only.ant-btn-sm{width:24px;height:24px;padding:0;font-size:14px;border-radius:3px}.ant-btn-icon-only.ant-btn-sm>*{font-size:14px}.ant-btn-round{height:32px;padding:4px 16px;font-size:14px;border-radius:32px}.ant-btn-round.ant-btn-lg{height:40px;padding:6.4px 20px;font-size:16px;border-radius:40px}.ant-btn-round.ant-btn-sm{height:24px;padding:0 12px;font-size:14px;border-radius:24px}.ant-btn-round.ant-btn-icon-only{width:auto}.ant-btn-circle,.ant-btn-circle-outline{min-width:32px;padding-right:0;padding-left:0;text-align:center;border-radius:50%}.ant-btn-circle.ant-btn-lg,.ant-btn-circle-outline.ant-btn-lg{min-width:40px;border-radius:50%}.ant-btn-circle.ant-btn-sm,.ant-btn-circle-outline.ant-btn-sm{min-width:24px;border-radius:50%}.ant-btn:before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:1;display:none;background:#fff;border-radius:inherit;opacity:.35;transition:opacity .2s;content:"";pointer-events:none}.ant-btn .anticon{transition:margin-left .3s cubic-bezier(.645,.045,.355,1)}.ant-btn .anticon.anticon-plus>svg,.ant-btn .anticon.anticon-minus>svg{shape-rendering:optimizeSpeed}.ant-btn.ant-btn-loading{position:relative}.ant-btn.ant-btn-loading:not([disabled]){pointer-events:none}.ant-btn.ant-btn-loading:before{display:block}.ant-btn>.ant-btn-loading-icon{transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-btn>.ant-btn-loading-icon .anticon{padding-right:8px}.ant-btn>.ant-btn-loading-icon:only-child .anticon{padding-right:0}.ant-btn-group{position:relative;display:inline-flex}.ant-btn-group>.ant-btn,.ant-btn-group>span>.ant-btn{position:relative}.ant-btn-group>.ant-btn:hover,.ant-btn-group>span>.ant-btn:hover,.ant-btn-group>.ant-btn:focus,.ant-btn-group>span>.ant-btn:focus,.ant-btn-group>.ant-btn:active,.ant-btn-group>span>.ant-btn:active,.ant-btn-group>.ant-btn.active,.ant-btn-group>span>.ant-btn.active{z-index:2}.ant-btn-group>.ant-btn:disabled,.ant-btn-group>span>.ant-btn:disabled{z-index:0}.ant-btn-group .ant-btn-icon-only{font-size:14px}.ant-btn-group-lg>.ant-btn,.ant-btn-group-lg>span>.ant-btn{height:40px;padding:6.4px 15px;font-size:16px;border-radius:0}.ant-btn-group-lg .ant-btn.ant-btn-icon-only{width:40px;height:40px;padding-right:0;padding-left:0}.ant-btn-group-sm>.ant-btn,.ant-btn-group-sm>span>.ant-btn{height:24px;padding:0 7px;font-size:14px;border-radius:0}.ant-btn-group-sm>.ant-btn>.anticon,.ant-btn-group-sm>span>.ant-btn>.anticon{font-size:14px}.ant-btn-group-sm .ant-btn.ant-btn-icon-only{width:24px;height:24px;padding-right:0;padding-left:0}.ant-btn-group .ant-btn+.ant-btn,.ant-btn+.ant-btn-group,.ant-btn-group span+.ant-btn,.ant-btn-group .ant-btn+span,.ant-btn-group>span+span,.ant-btn-group+.ant-btn,.ant-btn-group+.ant-btn-group{margin-left:-1px}.ant-btn-group .ant-btn-primary+.ant-btn:not(.ant-btn-primary):not([disabled]){border-left-color:transparent}.ant-btn-group .ant-btn{border-radius:0}.ant-btn-group>.ant-btn:first-child,.ant-btn-group>span:first-child>.ant-btn{margin-left:0}.ant-btn-group>.ant-btn:only-child{border-radius:3px}.ant-btn-group>span:only-child>.ant-btn{border-radius:3px}.ant-btn-group>.ant-btn:first-child:not(:last-child),.ant-btn-group>span:first-child:not(:last-child)>.ant-btn{border-top-left-radius:3px;border-bottom-left-radius:3px}.ant-btn-group>.ant-btn:last-child:not(:first-child),.ant-btn-group>span:last-child:not(:first-child)>.ant-btn{border-top-right-radius:3px;border-bottom-right-radius:3px}.ant-btn-group-sm>.ant-btn:only-child{border-radius:3px}.ant-btn-group-sm>span:only-child>.ant-btn{border-radius:3px}.ant-btn-group-sm>.ant-btn:first-child:not(:last-child),.ant-btn-group-sm>span:first-child:not(:last-child)>.ant-btn{border-top-left-radius:3px;border-bottom-left-radius:3px}.ant-btn-group-sm>.ant-btn:last-child:not(:first-child),.ant-btn-group-sm>span:last-child:not(:first-child)>.ant-btn{border-top-right-radius:3px;border-bottom-right-radius:3px}.ant-btn-group>.ant-btn-group{float:left}.ant-btn-group>.ant-btn-group:not(:first-child):not(:last-child)>.ant-btn{border-radius:0}.ant-btn-group>.ant-btn-group:first-child:not(:last-child)>.ant-btn:last-child{padding-right:8px;border-top-right-radius:0;border-bottom-right-radius:0}.ant-btn-group>.ant-btn-group:last-child:not(:first-child)>.ant-btn:first-child{padding-left:8px;border-top-left-radius:0;border-bottom-left-radius:0}.ant-btn-rtl.ant-btn-group .ant-btn+.ant-btn,.ant-btn-rtl.ant-btn+.ant-btn-group,.ant-btn-rtl.ant-btn-group span+.ant-btn,.ant-btn-rtl.ant-btn-group .ant-btn+span,.ant-btn-rtl.ant-btn-group>span+span,.ant-btn-rtl.ant-btn-group+.ant-btn,.ant-btn-rtl.ant-btn-group+.ant-btn-group,.ant-btn-group-rtl.ant-btn-group .ant-btn+.ant-btn,.ant-btn-group-rtl.ant-btn+.ant-btn-group,.ant-btn-group-rtl.ant-btn-group span+.ant-btn,.ant-btn-group-rtl.ant-btn-group .ant-btn+span,.ant-btn-group-rtl.ant-btn-group>span+span,.ant-btn-group-rtl.ant-btn-group+.ant-btn,.ant-btn-group-rtl.ant-btn-group+.ant-btn-group{margin-right:-1px;margin-left:auto}.ant-btn-group.ant-btn-group-rtl{direction:rtl}.ant-btn-group-rtl.ant-btn-group>.ant-btn:first-child:not(:last-child),.ant-btn-group-rtl.ant-btn-group>span:first-child:not(:last-child)>.ant-btn{border-radius:0 3px 3px 0}.ant-btn-group-rtl.ant-btn-group>.ant-btn:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group>span:last-child:not(:first-child)>.ant-btn{border-radius:3px 0 0 3px}.ant-btn-group-rtl.ant-btn-group-sm>.ant-btn:first-child:not(:last-child),.ant-btn-group-rtl.ant-btn-group-sm>span:first-child:not(:last-child)>.ant-btn{border-radius:0 3px 3px 0}.ant-btn-group-rtl.ant-btn-group-sm>.ant-btn:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group-sm>span:last-child:not(:first-child)>.ant-btn{border-radius:3px 0 0 3px}.ant-btn:focus>span,.ant-btn:active>span{position:relative}.ant-btn>.anticon+span,.ant-btn>span+.anticon{margin-left:6px}.ant-btn-background-ghost{color:#fff;background:transparent!important;border-color:#fff}.ant-btn-background-ghost:hover{border-color:#0052d9}.ant-btn-background-ghost.ant-btn-primary{color:#0052d9;background-color:transparent;border-color:#0052d9;text-shadow:none}.ant-btn-background-ghost.ant-btn-primary>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-primary:hover,.ant-btn-background-ghost.ant-btn-primary:focus{color:#2575e6;background-color:transparent;border-color:#2575e6}.ant-btn-background-ghost.ant-btn-primary:hover>a:only-child,.ant-btn-background-ghost.ant-btn-primary:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-primary:active,.ant-btn-background-ghost.ant-btn-primary.active{color:#003eb3;background-color:transparent;border-color:#003eb3}.ant-btn-background-ghost.ant-btn-primary:active>a:only-child,.ant-btn-background-ghost.ant-btn-primary.active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-primary:active>a:only-child:after,.ant-btn-background-ghost.ant-btn-primary.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-primary-disabled,.ant-btn-background-ghost.ant-btn-primary.disabled,.ant-btn-background-ghost.ant-btn-primary[disabled],.ant-btn-background-ghost.ant-btn-primary-disabled:hover,.ant-btn-background-ghost.ant-btn-primary.disabled:hover,.ant-btn-background-ghost.ant-btn-primary[disabled]:hover,.ant-btn-background-ghost.ant-btn-primary-disabled:focus,.ant-btn-background-ghost.ant-btn-primary.disabled:focus,.ant-btn-background-ghost.ant-btn-primary[disabled]:focus,.ant-btn-background-ghost.ant-btn-primary-disabled:active,.ant-btn-background-ghost.ant-btn-primary.disabled:active,.ant-btn-background-ghost.ant-btn-primary[disabled]:active,.ant-btn-background-ghost.ant-btn-primary-disabled.active,.ant-btn-background-ghost.ant-btn-primary.disabled.active,.ant-btn-background-ghost.ant-btn-primary[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-background-ghost.ant-btn-primary:hover{border-color:#8592a6}.ant-btn-background-ghost.ant-btn-danger{color:#e34d59;background-color:transparent;border-color:#e34d59;text-shadow:none}.ant-btn-background-ghost.ant-btn-danger>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-danger:hover,.ant-btn-background-ghost.ant-btn-danger:focus{color:#f0787e;background-color:transparent;border-color:#f0787e}.ant-btn-background-ghost.ant-btn-danger:hover>a:only-child,.ant-btn-background-ghost.ant-btn-danger:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-danger:active,.ant-btn-background-ghost.ant-btn-danger.active{color:#bd3746;background-color:transparent;border-color:#bd3746}.ant-btn-background-ghost.ant-btn-danger:active>a:only-child,.ant-btn-background-ghost.ant-btn-danger.active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-danger:active>a:only-child:after,.ant-btn-background-ghost.ant-btn-danger.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-danger-disabled,.ant-btn-background-ghost.ant-btn-danger.disabled,.ant-btn-background-ghost.ant-btn-danger[disabled],.ant-btn-background-ghost.ant-btn-danger-disabled:hover,.ant-btn-background-ghost.ant-btn-danger.disabled:hover,.ant-btn-background-ghost.ant-btn-danger[disabled]:hover,.ant-btn-background-ghost.ant-btn-danger-disabled:focus,.ant-btn-background-ghost.ant-btn-danger.disabled:focus,.ant-btn-background-ghost.ant-btn-danger[disabled]:focus,.ant-btn-background-ghost.ant-btn-danger-disabled:active,.ant-btn-background-ghost.ant-btn-danger.disabled:active,.ant-btn-background-ghost.ant-btn-danger[disabled]:active,.ant-btn-background-ghost.ant-btn-danger-disabled.active,.ant-btn-background-ghost.ant-btn-danger.disabled.active,.ant-btn-background-ghost.ant-btn-danger[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-background-ghost.ant-btn-dangerous{color:#e34d59;background-color:transparent;border-color:#e34d59;text-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous:hover,.ant-btn-background-ghost.ant-btn-dangerous:focus{color:#f0787e;background-color:transparent;border-color:#f0787e}.ant-btn-background-ghost.ant-btn-dangerous:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous:active,.ant-btn-background-ghost.ant-btn-dangerous.active{color:#bd3746;background-color:transparent;border-color:#bd3746}.ant-btn-background-ghost.ant-btn-dangerous:active>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous:active>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous-disabled,.ant-btn-background-ghost.ant-btn-dangerous.disabled,.ant-btn-background-ghost.ant-btn-dangerous[disabled],.ant-btn-background-ghost.ant-btn-dangerous-disabled:hover,.ant-btn-background-ghost.ant-btn-dangerous.disabled:hover,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:hover,.ant-btn-background-ghost.ant-btn-dangerous-disabled:focus,.ant-btn-background-ghost.ant-btn-dangerous.disabled:focus,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:focus,.ant-btn-background-ghost.ant-btn-dangerous-disabled:active,.ant-btn-background-ghost.ant-btn-dangerous.disabled:active,.ant-btn-background-ghost.ant-btn-dangerous[disabled]:active,.ant-btn-background-ghost.ant-btn-dangerous-disabled.active,.ant-btn-background-ghost.ant-btn-dangerous.disabled.active,.ant-btn-background-ghost.ant-btn-dangerous[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link{color:#e34d59;background-color:transparent;border-color:transparent;text-shadow:none}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus{color:#f0787e;background-color:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.active{color:#bd3746;background-color:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active>a:only-child,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link:active>a:only-child:after,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link-disabled,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.disabled,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled],.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link-disabled:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.disabled:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:hover,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link-disabled:focus,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.disabled:focus,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:focus,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link-disabled:active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.disabled:active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled]:active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link-disabled.active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link.disabled.active,.ant-btn-background-ghost.ant-btn-dangerous.ant-btn-link[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-background-ghost.ant-btn-link{color:#0052d9;background-color:transparent;border-color:transparent;text-shadow:none;color:#fff}.ant-btn-background-ghost.ant-btn-link>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-link>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-link:hover,.ant-btn-background-ghost.ant-btn-link:focus{color:#2575e6;background-color:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-link:hover>a:only-child,.ant-btn-background-ghost.ant-btn-link:focus>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-link:hover>a:only-child:after,.ant-btn-background-ghost.ant-btn-link:focus>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-link:active,.ant-btn-background-ghost.ant-btn-link.active{color:#003eb3;background-color:transparent;border-color:transparent}.ant-btn-background-ghost.ant-btn-link:active>a:only-child,.ant-btn-background-ghost.ant-btn-link.active>a:only-child{color:currentColor}.ant-btn-background-ghost.ant-btn-link:active>a:only-child:after,.ant-btn-background-ghost.ant-btn-link.active>a:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;background:transparent;content:""}.ant-btn-background-ghost.ant-btn-link-disabled,.ant-btn-background-ghost.ant-btn-link.disabled,.ant-btn-background-ghost.ant-btn-link[disabled],.ant-btn-background-ghost.ant-btn-link-disabled:hover,.ant-btn-background-ghost.ant-btn-link.disabled:hover,.ant-btn-background-ghost.ant-btn-link[disabled]:hover,.ant-btn-background-ghost.ant-btn-link-disabled:focus,.ant-btn-background-ghost.ant-btn-link.disabled:focus,.ant-btn-background-ghost.ant-btn-link[disabled]:focus,.ant-btn-background-ghost.ant-btn-link-disabled:active,.ant-btn-background-ghost.ant-btn-link.disabled:active,.ant-btn-background-ghost.ant-btn-link[disabled]:active,.ant-btn-background-ghost.ant-btn-link-disabled.active,.ant-btn-background-ghost.ant-btn-link.disabled.active,.ant-btn-background-ghost.ant-btn-link[disabled].active{text-shadow:none;box-shadow:none;opacity:.3}.ant-btn-two-chinese-chars:first-letter{letter-spacing:.34em}.ant-btn-two-chinese-chars>*:not(.anticon){margin-right:-.34em;letter-spacing:.34em}.ant-btn-block{width:100%}.ant-btn:empty{display:inline-block;width:0;visibility:hidden;content:"\a0"}a.ant-btn{padding-top:.1px;line-height:30px}a.ant-btn-lg{line-height:38px}a.ant-btn-md{line-height:30px}a.ant-btn-sm{line-height:22px}.ant-btn-rtl{direction:rtl}.ant-btn-group-rtl.ant-btn-group .ant-btn-primary:last-child:not(:first-child),.ant-btn-group-rtl.ant-btn-group .ant-btn-primary+.ant-btn-primary{border-right-color:#2575e6;border-left-color:#d9d9d9}.ant-btn-group-rtl.ant-btn-group .ant-btn-primary:last-child:not(:first-child)[disabled],.ant-btn-group-rtl.ant-btn-group .ant-btn-primary+.ant-btn-primary[disabled]{border-right-color:#d9d9d9;border-left-color:#2575e6}.ant-btn-rtl.ant-btn>.ant-btn-loading-icon .anticon{padding-right:0;padding-left:8px}.ant-btn>.ant-btn-loading-icon:only-child .anticon{padding-right:0;padding-left:0}.ant-btn-rtl.ant-btn>.anticon+span,.ant-btn-rtl.ant-btn>span+.anticon{margin-right:8px;margin-left:0}.ant-picker-calendar{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background:#fff}.ant-picker-calendar-header{display:flex;justify-content:flex-end;padding:12px 0}.ant-picker-calendar-header .ant-picker-calendar-year-select{min-width:80px}.ant-picker-calendar-header .ant-picker-calendar-month-select{min-width:70px;margin-left:8px}.ant-picker-calendar-header .ant-picker-calendar-mode-switch{margin-left:8px}.ant-picker-calendar .ant-picker-panel{background:#fff;border:0;border-top:1px solid #f0f0f0;border-radius:0}.ant-picker-calendar .ant-picker-panel .ant-picker-month-panel,.ant-picker-calendar .ant-picker-panel .ant-picker-date-panel{width:auto}.ant-picker-calendar .ant-picker-panel .ant-picker-body{padding:8px 0}.ant-picker-calendar .ant-picker-panel .ant-picker-content{width:100%}.ant-picker-calendar-mini{border-radius:3px}.ant-picker-calendar-mini .ant-picker-calendar-header{padding-right:8px;padding-left:8px}.ant-picker-calendar-mini .ant-picker-panel{border-radius:0 0 3px 3px}.ant-picker-calendar-mini .ant-picker-content{height:256px}.ant-picker-calendar-mini .ant-picker-content th{height:auto;padding:0;line-height:18px}.ant-picker-calendar-full .ant-picker-panel{display:block;width:100%;text-align:right;background:#fff;border:0}.ant-picker-calendar-full .ant-picker-panel .ant-picker-body th,.ant-picker-calendar-full .ant-picker-panel .ant-picker-body td{padding:0}.ant-picker-calendar-full .ant-picker-panel .ant-picker-body th{height:auto;padding:0 12px 5px 0;line-height:18px}.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell:before{display:none}.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell:hover .ant-picker-calendar-date{background:#f3f3f3}.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell .ant-picker-calendar-date-today:before{display:none}.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected .ant-picker-calendar-date,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected:hover .ant-picker-calendar-date,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected .ant-picker-calendar-date-today,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected:hover .ant-picker-calendar-date-today{background:#e0ebff}.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected .ant-picker-calendar-date .ant-picker-calendar-date-value,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected:hover .ant-picker-calendar-date .ant-picker-calendar-date-value,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected .ant-picker-calendar-date-today .ant-picker-calendar-date-value,.ant-picker-calendar-full .ant-picker-panel .ant-picker-cell-selected:hover .ant-picker-calendar-date-today .ant-picker-calendar-date-value{color:#0052d9}.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date{display:block;width:auto;height:auto;margin:0 4px;padding:4px 8px 0;border:0;border-top:2px solid #f0f0f0;border-radius:0;transition:background .3s}.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-value{line-height:24px;transition:color .3s}.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-content{position:static;width:auto;height:86px;overflow-y:auto;color:#000a29e6;line-height:1.5715;text-align:left}.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today{border-color:#0052d9}.ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today .ant-picker-calendar-date-value{color:#000a29e6}@media only screen and (max-width: 480px){.ant-picker-calendar-header{display:block}.ant-picker-calendar-header .ant-picker-calendar-year-select{width:50%}.ant-picker-calendar-header .ant-picker-calendar-month-select{width:calc(50% - 8px)}.ant-picker-calendar-header .ant-picker-calendar-mode-switch{width:100%;margin-top:8px;margin-left:0}.ant-picker-calendar-header .ant-picker-calendar-mode-switch>label{width:50%;text-align:center}}.ant-picker-calendar-rtl{direction:rtl}.ant-picker-calendar-rtl .ant-picker-calendar-header .ant-picker-calendar-month-select,.ant-picker-calendar-rtl .ant-picker-calendar-header .ant-picker-calendar-mode-switch{margin-right:8px;margin-left:0}.ant-picker-calendar-rtl.ant-picker-calendar-full .ant-picker-panel{text-align:left}.ant-picker-calendar-rtl.ant-picker-calendar-full .ant-picker-panel .ant-picker-body th{padding:0 0 5px 12px}.ant-card{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;background:#fff;border-radius:3px;transition:all .3s}.ant-card-rtl{direction:rtl}.ant-card-hoverable{cursor:pointer}.ant-card-hoverable:hover{border-color:transparent;box-shadow:0 1px 2px -2px #00000029,0 3px 6px #0000001f,0 5px 12px 4px #00000017}.ant-card-bordered{border:1px solid #f0f0f0}.ant-card-head{min-height:48px;margin-bottom:-1px;padding:0 24px;color:#000a29e6;font-weight:500;font-size:16px;background:transparent;border-bottom:1px solid #f0f0f0;border-radius:3px 3px 0 0}.ant-card-head:before{display:table;content:""}.ant-card-head:after{display:table;clear:both;content:""}.ant-card-head-wrapper{display:flex;align-items:center}.ant-card-head-title{display:inline-block;flex:1;padding:16px 0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-card-head .ant-tabs{clear:both;margin-bottom:-17px;color:#000a29e6;font-weight:400;font-size:14px}.ant-card-head .ant-tabs-bar{border-bottom:1px solid #f0f0f0}.ant-card-extra{float:right;margin-left:auto;padding:16px 0;color:#000a29e6;font-weight:400;font-size:14px}.ant-card-rtl .ant-card-extra{margin-right:auto;margin-left:0}.ant-card-body{padding:24px}.ant-card-body:before{display:table;content:""}.ant-card-body:after{display:table;clear:both;content:""}.ant-card-contain-grid:not(.ant-card-loading) .ant-card-body{margin:-1px 0 0 -1px;padding:0}.ant-card-grid{float:left;width:33.33%;padding:24px;border:0;border-radius:0;box-shadow:1px 0 #f0f0f0,0 1px #f0f0f0,1px 1px #f0f0f0,1px 0 #f0f0f0 inset,0 1px #f0f0f0 inset;transition:all .3s}.ant-card-rtl .ant-card-grid{float:right}.ant-card-grid-hoverable:hover{position:relative;z-index:1;box-shadow:0 1px 2px -2px #00000029,0 3px 6px #0000001f,0 5px 12px 4px #00000017}.ant-card-contain-tabs>.ant-card-head .ant-card-head-title{min-height:32px;padding-bottom:0}.ant-card-contain-tabs>.ant-card-head .ant-card-extra{padding-bottom:0}.ant-card-cover{margin-right:-1px;margin-left:-1px}.ant-card-cover>*{display:block;width:100%}.ant-card-cover img{border-radius:3px 3px 0 0}.ant-card-actions{margin:0;padding:0;list-style:none;background:#f1f2f5;border-top:1px solid #f0f0f0}.ant-card-actions:before{display:table;content:""}.ant-card-actions:after{display:table;clear:both;content:""}.ant-card-actions>li{float:left;margin:12px 0;color:#000a2999;text-align:center}.ant-card-rtl .ant-card-actions>li{float:right}.ant-card-actions>li>span{position:relative;display:block;min-width:32px;font-size:14px;line-height:1.5715;cursor:pointer}.ant-card-actions>li>span:hover{color:#0052d9;transition:color .3s}.ant-card-actions>li>span a:not(.ant-btn),.ant-card-actions>li>span>.anticon{display:inline-block;width:100%;color:#000a2999;line-height:22px;transition:color .3s}.ant-card-actions>li>span a:not(.ant-btn):hover,.ant-card-actions>li>span>.anticon:hover{color:#0052d9}.ant-card-actions>li>span>.anticon{font-size:16px;line-height:22px}.ant-card-actions>li:not(:last-child){border-right:1px solid #f0f0f0}.ant-card-type-inner .ant-card-head{padding:0 24px;background:#f1f2f5}.ant-card-type-inner .ant-card-head-title{padding:12px 0;font-size:14px}.ant-card-type-inner .ant-card-body{padding:16px 24px}.ant-card-type-inner .ant-card-extra{padding:13.5px 0}.ant-card-meta{margin:-4px 0}.ant-card-meta:before{display:table;content:""}.ant-card-meta:after{display:table;clear:both;content:""}.ant-card-meta-avatar{float:left;padding-right:16px}.ant-card-rtl .ant-card-meta-avatar{float:right;padding-right:0;padding-left:16px}.ant-card-meta-detail{overflow:hidden}.ant-card-meta-detail>div:not(:last-child){margin-bottom:8px}.ant-card-meta-title{overflow:hidden;color:#000a29e6;font-weight:500;font-size:16px;white-space:nowrap;text-overflow:ellipsis}.ant-card-meta-description{color:#000a2999}.ant-card-loading{overflow:hidden}.ant-card-loading .ant-card-body{user-select:none}.ant-card-loading-content p{margin:0}.ant-card-loading-block{height:14px;margin:4px 0;background:linear-gradient(90deg,rgba(207,216,220,.2),rgba(207,216,220,.4),rgba(207,216,220,.2));background-size:600% 600%;border-radius:3px;animation:card-loading 1.4s ease infinite}@keyframes card-loading{0%,to{background-position:0 50%}50%{background-position:100% 50%}}.ant-card-small>.ant-card-head{min-height:36px;padding:0 12px;font-size:14px}.ant-card-small>.ant-card-head>.ant-card-head-wrapper>.ant-card-head-title{padding:8px 0}.ant-card-small>.ant-card-head>.ant-card-head-wrapper>.ant-card-extra{padding:8px 0;font-size:14px}.ant-card-small>.ant-card-body{padding:12px}.ant-carousel{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum"}.ant-carousel .slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-touch-callout:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.ant-carousel .slick-list{position:relative;display:block;margin:0;padding:0;overflow:hidden}.ant-carousel .slick-list:focus{outline:none}.ant-carousel .slick-list.dragging{cursor:pointer}.ant-carousel .slick-list .slick-slide{pointer-events:none}.ant-carousel .slick-list .slick-slide input.ant-radio-input,.ant-carousel .slick-list .slick-slide input.ant-checkbox-input{visibility:hidden}.ant-carousel .slick-list .slick-slide.slick-active{pointer-events:auto}.ant-carousel .slick-list .slick-slide.slick-active input.ant-radio-input,.ant-carousel .slick-list .slick-slide.slick-active input.ant-checkbox-input{visibility:visible}.ant-carousel .slick-slider .slick-track,.ant-carousel .slick-slider .slick-list{transform:translateZ(0)}.ant-carousel .slick-track{position:relative;top:0;left:0;display:block}.ant-carousel .slick-track:before,.ant-carousel .slick-track:after{display:table;content:""}.ant-carousel .slick-track:after{clear:both}.slick-loading .ant-carousel .slick-track{visibility:hidden}.ant-carousel .slick-slide{display:none;float:left;height:100%;min-height:1px}.ant-carousel .slick-slide img{display:block}.ant-carousel .slick-slide.slick-loading img{display:none}.ant-carousel .slick-slide.dragging img{pointer-events:none}.ant-carousel .slick-initialized .slick-slide{display:block}.ant-carousel .slick-loading .slick-slide{visibility:hidden}.ant-carousel .slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.ant-carousel .slick-arrow.slick-hidden{display:none}.ant-carousel .slick-prev,.ant-carousel .slick-next{position:absolute;top:50%;display:block;width:20px;height:20px;margin-top:-10px;padding:0;color:transparent;font-size:0;line-height:0;background:transparent;border:0;outline:none;cursor:pointer}.ant-carousel .slick-prev:hover,.ant-carousel .slick-next:hover,.ant-carousel .slick-prev:focus,.ant-carousel .slick-next:focus{color:transparent;background:transparent;outline:none}.ant-carousel .slick-prev:hover:before,.ant-carousel .slick-next:hover:before,.ant-carousel .slick-prev:focus:before,.ant-carousel .slick-next:focus:before{opacity:1}.ant-carousel .slick-prev.slick-disabled:before,.ant-carousel .slick-next.slick-disabled:before{opacity:.25}.ant-carousel .slick-prev{left:-25px}.ant-carousel .slick-prev:before{content:"\2190"}.ant-carousel .slick-next{right:-25px}.ant-carousel .slick-next:before{content:"\2192"}.ant-carousel .slick-dots{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex!important;justify-content:center;margin-right:15%;margin-left:15%;padding-left:0;list-style:none}.ant-carousel .slick-dots-bottom{bottom:12px}.ant-carousel .slick-dots-top{top:12px}.ant-carousel .slick-dots li{position:relative;display:inline-block;flex:0 1 auto;box-sizing:content-box;width:16px;height:3px;margin:0 3px;padding:0;text-align:center;text-indent:-999px;vertical-align:top;transition:all .5s}.ant-carousel .slick-dots li button{display:block;width:100%;height:3px;padding:0;color:transparent;font-size:0;background:#fff;border:0;border-radius:1px;outline:none;cursor:pointer;opacity:.3;transition:all .5s}.ant-carousel .slick-dots li button:hover,.ant-carousel .slick-dots li button:focus{opacity:.75}.ant-carousel .slick-dots li.slick-active{width:24px}.ant-carousel .slick-dots li.slick-active button{background:#fff;opacity:1}.ant-carousel .slick-dots li.slick-active:hover,.ant-carousel .slick-dots li.slick-active:focus{opacity:1}.ant-carousel-vertical .slick-dots{top:50%;bottom:auto;flex-direction:column;width:3px;height:auto;margin:0;transform:translateY(-50%)}.ant-carousel-vertical .slick-dots-left{right:auto;left:12px}.ant-carousel-vertical .slick-dots-right{right:12px;left:auto}.ant-carousel-vertical .slick-dots li{width:3px;height:16px;margin:4px 2px;vertical-align:baseline}.ant-carousel-vertical .slick-dots li button{width:3px;height:16px}.ant-carousel-vertical .slick-dots li.slick-active,.ant-carousel-vertical .slick-dots li.slick-active button{width:3px;height:24px}.ant-carousel-rtl{direction:rtl}.ant-carousel-rtl .ant-carousel .slick-track{right:0;left:auto}.ant-carousel-rtl .ant-carousel .slick-prev{right:-25px;left:auto}.ant-carousel-rtl .ant-carousel .slick-prev:before{content:"\2192"}.ant-carousel-rtl .ant-carousel .slick-next{right:auto;left:-25px}.ant-carousel-rtl .ant-carousel .slick-next:before{content:"\2190"}.ant-carousel-rtl.ant-carousel .slick-dots{flex-direction:row-reverse}.ant-carousel-rtl.ant-carousel-vertical .slick-dots{flex-direction:column}.ant-cascader{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum"}.ant-cascader-input.ant-input{position:static;width:100%;padding-right:24px;background-color:transparent!important;cursor:pointer}.ant-cascader-picker-show-search .ant-cascader-input.ant-input{position:relative}.ant-cascader-picker{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;background-color:#fff;border-radius:3px;outline:0;cursor:pointer;transition:color .3s}.ant-cascader-picker-with-value .ant-cascader-picker-label{color:transparent}.ant-cascader-picker-disabled{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-cascader-picker-disabled .ant-cascader-input{cursor:not-allowed}.ant-cascader-picker:focus .ant-cascader-input{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-cascader-picker:focus .ant-cascader-input{border-right-width:0;border-left-width:1px!important}.ant-cascader-picker-borderless .ant-cascader-input{border-color:transparent!important;box-shadow:none!important}.ant-cascader-picker-show-search.ant-cascader-picker-focused{color:#00000040}.ant-cascader-picker-label{position:absolute;top:50%;left:0;width:100%;height:20px;margin-top:-10px;padding:0 20px 0 8px;overflow:hidden;line-height:20px;white-space:nowrap;text-overflow:ellipsis}.ant-cascader-picker-clear{position:absolute;top:50%;right:8px;z-index:2;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;line-height:12px;background:#fff;cursor:pointer;opacity:0;transition:color .3s ease,opacity .15s ease}.ant-cascader-picker-clear:hover{color:#000a2999}.ant-cascader-picker:hover .ant-cascader-picker-clear{opacity:1}.ant-cascader-picker-arrow{position:absolute;top:50%;right:8px;z-index:1;width:12px;height:12px;margin-top:-6px;color:#00000040;font-size:12px;line-height:12px;transition:transform .2s}.ant-cascader-picker-arrow.ant-cascader-picker-arrow-expand{transform:rotate(180deg)}.ant-cascader-picker-label:hover+.ant-cascader-input{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-cascader-picker-label:hover+.ant-cascader-input{border-right-width:0;border-left-width:1px!important}.ant-cascader-picker-small .ant-cascader-picker-clear,.ant-cascader-picker-small .ant-cascader-picker-arrow{right:8px}.ant-cascader-menus{position:absolute;z-index:1050;font-size:14px;white-space:nowrap;background:#fff;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-cascader-menus ul,.ant-cascader-menus ol{margin:0;list-style:none}.ant-cascader-menus-empty,.ant-cascader-menus-hidden{display:none}.ant-cascader-menus.slide-up-enter.slide-up-enter-active.ant-cascader-menus-placement-bottomLeft,.ant-cascader-menus.slide-up-appear.slide-up-appear-active.ant-cascader-menus-placement-bottomLeft{animation-name:antSlideUpIn}.ant-cascader-menus.slide-up-enter.slide-up-enter-active.ant-cascader-menus-placement-topLeft,.ant-cascader-menus.slide-up-appear.slide-up-appear-active.ant-cascader-menus-placement-topLeft{animation-name:antSlideDownIn}.ant-cascader-menus.slide-up-leave.slide-up-leave-active.ant-cascader-menus-placement-bottomLeft{animation-name:antSlideUpOut}.ant-cascader-menus.slide-up-leave.slide-up-leave-active.ant-cascader-menus-placement-topLeft{animation-name:antSlideDownOut}.ant-cascader-menu{display:inline-block;min-width:111px;height:180px;margin:0;padding:4px 0;overflow:auto;vertical-align:top;list-style:none;border-right:1px solid #f0f0f0;-ms-overflow-style:-ms-autohiding-scrollbar}.ant-cascader-menu:first-child{border-radius:3px 0 0 3px}.ant-cascader-menu:last-child{margin-right:-1px;border-right-color:transparent;border-radius:0 3px 3px 0}.ant-cascader-menu:only-child{border-radius:3px}.ant-cascader-menu-item{padding:5px 8px;line-height:22px;white-space:nowrap;cursor:pointer;transition:all .3s}.ant-cascader-menu-item:hover{background:#f3f3f3}.ant-cascader-menu-item-disabled{color:#00000040;cursor:not-allowed}.ant-cascader-menu-item-disabled:hover{background:transparent}.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled),.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled):hover{font-weight:600;background-color:#e6f4ff}.ant-cascader-menu-item-expand{position:relative;padding-right:24px}.ant-cascader-menu-item-expand .ant-cascader-menu-item-expand-icon,.ant-cascader-menu-item-loading-icon{display:inline-block;font-size:10px;position:absolute;right:8px;color:#000a2999}.ant-cascader-menu-item .ant-cascader-menu-item-keyword{color:#e34d59}.ant-cascader-picker-rtl .ant-cascader-input.ant-input{padding-right:8px;padding-left:24px;text-align:right}.ant-cascader-picker-rtl{direction:rtl}.ant-cascader-picker-rtl .ant-cascader-picker-label{padding:0 8px 0 20px;text-align:right}.ant-cascader-picker-rtl .ant-cascader-picker-clear,.ant-cascader-picker-rtl .ant-cascader-picker-arrow,.ant-cascader-picker-rtl.ant-cascader-picker-small .ant-cascader-picker-clear,.ant-cascader-picker-rtl.ant-cascader-picker-small .ant-cascader-picker-arrow{right:auto;left:8px}.ant-cascader-menu-rtl{direction:rtl;border-right:none;border-left:1px solid #f0f0f0}.ant-cascader-menu-rtl:last-child{margin-right:0;margin-left:-1px;border-left-color:transparent;border-radius:0 0 4px 4px}.ant-cascader-menu-rtl .ant-cascader-menu-item-expand{padding-right:8px;padding-left:24px}.ant-cascader-menu-rtl .ant-cascader-menu-item-expand .ant-cascader-menu-item-expand-icon,.ant-cascader-menu-rtl .ant-cascader-menu-item-loading-icon{right:auto;left:8px}@keyframes antCheckboxEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}.ant-checkbox-checked .ant-checkbox-inner{background-color:#0052d9}.ant-checkbox-checked .ant-checkbox-inner:after{border-color:#fff!important}.ant-checkbox-disabled .ant-checkbox-inner:after{border-color:#000a2942!important}.ant-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-checkbox-wrapper:hover .ant-checkbox-inner,.ant-checkbox:hover .ant-checkbox-inner,.ant-checkbox-input:focus+.ant-checkbox-inner{border-color:#0052d9}.ant-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #0052d9;border-radius:3px;visibility:hidden;animation:antCheckboxEffect .36s ease-in-out;animation-fill-mode:backwards;content:""}.ant-checkbox:hover:after,.ant-checkbox-wrapper:hover .ant-checkbox:after{visibility:visible}.ant-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;direction:ltr;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;border-collapse:separate}.ant-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5px;height:8px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:" "}.ant-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-checkbox-checked .ant-checkbox-inner:after{position:absolute;display:table;border:2px solid #0052d9;border-top:0;border-left:0;transform:rotate(45deg) scale(1.2) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:" "}.ant-checkbox-checked .ant-checkbox-inner{border-color:#0052d9}.ant-checkbox-disabled{cursor:not-allowed}.ant-checkbox-disabled.ant-checkbox-checked .ant-checkbox-inner:after{border-color:#00000040;animation-name:none}.ant-checkbox-disabled .ant-checkbox-input{cursor:not-allowed}.ant-checkbox-disabled .ant-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-checkbox-disabled .ant-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;animation-name:none}.ant-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-checkbox-disabled:hover:after,.ant-checkbox-wrapper:hover .ant-checkbox-disabled:after{visibility:hidden}.ant-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block;line-height:unset;cursor:pointer}.ant-checkbox-wrapper.ant-checkbox-wrapper-disabled{cursor:not-allowed}.ant-checkbox-wrapper+.ant-checkbox-wrapper{margin-left:8px}.ant-checkbox+span{padding-right:8px;padding-left:8px}.ant-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block}.ant-checkbox-group-item{display:inline-block;margin-right:8px}.ant-checkbox-group-item:last-child{margin-right:0}.ant-checkbox-group-item+.ant-checkbox-group-item{margin-left:0}.ant-checkbox-indeterminate .ant-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-checkbox-indeterminate .ant-checkbox-inner:after{top:50%;left:50%;width:8px;height:3px;background-color:#0052d9;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;transition:none;content:" "}.ant-checkbox-indeterminate.ant-checkbox-disabled .ant-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-checkbox-rtl{direction:rtl}.ant-checkbox-group-rtl .ant-checkbox-group-item{margin-right:0;margin-left:8px}.ant-checkbox-group-rtl .ant-checkbox-group-item:last-child{margin-left:0!important}.ant-checkbox-group-rtl .ant-checkbox-group-item+.ant-checkbox-group-item{margin-left:8px}.ant-collapse{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background-color:#f1f2f5;border:1px solid #d9d9d9;border-bottom:0;border-radius:3px}.ant-collapse>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse>.ant-collapse-item:last-child,.ant-collapse>.ant-collapse-item:last-child>.ant-collapse-header{border-radius:0 0 3px 3px}.ant-collapse>.ant-collapse-item>.ant-collapse-header{position:relative;padding:12px 16px 12px 40px;color:#000a29e6;line-height:1.5715;cursor:pointer;transition:all .3s}.ant-collapse>.ant-collapse-item>.ant-collapse-header:before{display:table;content:""}.ant-collapse>.ant-collapse-item>.ant-collapse-header:after{display:table;clear:both;content:""}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:50%;left:16px;display:inline-block;font-size:12px;transform:translateY(-50%)}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow>*{line-height:1}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{display:inline-block}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow:before{display:none}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow .ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow-icon{display:block}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transition:transform .24s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{float:right}.ant-collapse>.ant-collapse-item>.ant-collapse-header:focus{outline:none}.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-left:12px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header{padding:12px 40px 12px 16px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{right:16px;left:auto}.ant-collapse-anim-active{transition:height .2s cubic-bezier(.215,.61,.355,1)}.ant-collapse-content{overflow:hidden;color:#000a29e6;background-color:#fff;border-top:1px solid #d9d9d9}.ant-collapse-content>.ant-collapse-content-box{padding:16px}.ant-collapse-content-inactive{display:none}.ant-collapse-item:last-child>.ant-collapse-content{border-radius:0 0 3px 3px}.ant-collapse-borderless{background-color:#f1f2f5;border:0}.ant-collapse-borderless>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse-borderless>.ant-collapse-item:last-child,.ant-collapse-borderless>.ant-collapse-item:last-child .ant-collapse-header{border-radius:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:4px}.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#00000040;cursor:not-allowed}.ant-collapse-rtl{direction:rtl}.ant-collapse-rtl .ant-collapse>.ant-collapse-item>.ant-collapse-header{padding:12px 40px 12px 16px}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transform:rotate(180deg)}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{float:left}.ant-collapse-rtl.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-right:12px;padding-left:0}.ant-comment{position:relative;background-color:inherit}.ant-comment-inner{display:flex;padding:16px 0}.ant-comment-avatar{position:relative;flex-shrink:0;margin-right:12px;cursor:pointer}.ant-comment-avatar img{width:32px;height:32px;border-radius:50%}.ant-comment-content{position:relative;flex:1 1 auto;min-width:1px;font-size:14px;word-wrap:break-word}.ant-comment-content-author{display:flex;flex-wrap:wrap;justify-content:flex-start;margin-bottom:4px;font-size:14px}.ant-comment-content-author>a,.ant-comment-content-author>span{padding-right:8px;font-size:12px;line-height:18px}.ant-comment-content-author-name{color:#000a2999;font-size:14px;transition:color .3s}.ant-comment-content-author-name>*{color:#000a2999}.ant-comment-content-author-name>*:hover{color:#000a2999}.ant-comment-content-author-time{color:#ccc;white-space:nowrap;cursor:auto}.ant-comment-content-detail p{margin-bottom:inherit;white-space:pre-wrap}.ant-comment-actions{margin-top:12px;margin-bottom:inherit;padding-left:0}.ant-comment-actions>li{display:inline-block;color:#000a2999}.ant-comment-actions>li>span{padding-right:10px;color:#000a2999;font-size:12px;cursor:pointer;transition:color .3s;user-select:none}.ant-comment-actions>li>span:hover{color:#595959}.ant-comment-nested{margin-left:44px}.ant-comment-rtl{direction:rtl}.ant-comment-rtl .ant-comment-avatar{margin-right:0;margin-left:12px}.ant-comment-rtl .ant-comment-content-author>a,.ant-comment-rtl .ant-comment-content-author>span{padding-right:0;padding-left:8px}.ant-comment-rtl .ant-comment-actions{padding-right:0}.ant-comment-rtl .ant-comment-actions>li>span{padding-right:0;padding-left:10px}.ant-comment-rtl .ant-comment-nested{margin-right:44px;margin-left:0}.ant-picker-panel{display:inline-block;text-align:center;background:#fff;border:1px solid #f0f0f0;border-radius:3px;outline:none}.ant-picker-panel-focused{border-color:#0052d9}.ant-picker-decade-panel,.ant-picker-year-panel,.ant-picker-quarter-panel,.ant-picker-month-panel,.ant-picker-week-panel,.ant-picker-date-panel,.ant-picker-time-panel{display:flex;flex-direction:column;width:280px}.ant-picker-header{display:flex;padding:0 8px;color:#000a29e6;border-bottom:1px solid #f0f0f0}.ant-picker-header>*{flex:none}.ant-picker-header button{padding:0;color:#00000040;line-height:40px;background:transparent;border:0;cursor:pointer;transition:color .3s}.ant-picker-header>button{min-width:1.6em;font-size:14px}.ant-picker-header>button:hover{color:#000a29e6}.ant-picker-header-view{flex:auto;font-weight:500;line-height:40px}.ant-picker-header-view button{color:inherit;font-weight:inherit}.ant-picker-header-view button:not(:first-child){margin-left:8px}.ant-picker-header-view button:hover{color:#0052d9}.ant-picker-prev-icon,.ant-picker-next-icon,.ant-picker-super-prev-icon,.ant-picker-super-next-icon{position:relative;display:inline-block;width:7px;height:7px}.ant-picker-prev-icon:before,.ant-picker-next-icon:before,.ant-picker-super-prev-icon:before,.ant-picker-super-next-icon:before{position:absolute;top:0;left:0;display:inline-block;width:7px;height:7px;border:0 solid currentColor;border-width:1.5px 0 0 1.5px;content:""}.ant-picker-super-prev-icon:after,.ant-picker-super-next-icon:after{position:absolute;top:4px;left:4px;display:inline-block;width:7px;height:7px;border:0 solid currentColor;border-width:1.5px 0 0 1.5px;content:""}.ant-picker-prev-icon,.ant-picker-super-prev-icon{transform:rotate(-45deg)}.ant-picker-next-icon,.ant-picker-super-next-icon{transform:rotate(135deg)}.ant-picker-content{width:100%;table-layout:fixed;border-collapse:collapse}.ant-picker-content th,.ant-picker-content td{position:relative;min-width:24px;font-weight:400}.ant-picker-content th{height:30px;color:#000a29e6;line-height:30px}.ant-picker-cell{padding:3px 0;color:#00000040;cursor:pointer}.ant-picker-cell-in-view{color:#000a29e6}.ant-picker-cell-disabled{cursor:not-allowed}.ant-picker-cell:before{position:absolute;top:50%;right:0;left:0;z-index:1;height:24px;transform:translateY(-50%);content:""}.ant-picker-cell .ant-picker-cell-inner{position:relative;z-index:2;display:inline-block;min-width:24px;height:24px;line-height:24px;border-radius:3px;transition:background .3s,border .3s}.ant-picker-cell:hover:not(.ant-picker-cell-in-view) .ant-picker-cell-inner,.ant-picker-cell:hover:not(.ant-picker-cell-selected):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end):not(.ant-picker-cell-range-hover-start):not(.ant-picker-cell-range-hover-end) .ant-picker-cell-inner{background:#f3f3f3}.ant-picker-cell-in-view.ant-picker-cell-today .ant-picker-cell-inner:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;border:1px solid #0052d9;border-radius:3px;content:""}.ant-picker-cell-in-view.ant-picker-cell-in-range{position:relative}.ant-picker-cell-in-view.ant-picker-cell-in-range:before{background:#e6f4ff}.ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner,.ant-picker-cell-in-view.ant-picker-cell-range-start .ant-picker-cell-inner,.ant-picker-cell-in-view.ant-picker-cell-range-end .ant-picker-cell-inner{color:#fff;background:#0052d9}.ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single):before,.ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single):before{background:#e6f4ff}.ant-picker-cell-in-view.ant-picker-cell-range-start:before{left:50%}.ant-picker-cell-in-view.ant-picker-cell-range-end:before{right:50%}.ant-picker-cell-in-view.ant-picker-cell-range-hover-start:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end):after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:not(.ant-picker-cell-in-range):not(.ant-picker-cell-range-start):not(.ant-picker-cell-range-end):after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-range-start-single:after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-end.ant-picker-cell-range-end-single:after,.ant-picker-cell-in-view.ant-picker-cell-range-hover:not(.ant-picker-cell-in-range):after{position:absolute;top:50%;z-index:0;height:24px;border-top:1px dashed #4088ff;border-bottom:1px dashed #4088ff;transform:translateY(-50%);content:""}.ant-picker-cell-range-hover-start:after,.ant-picker-cell-range-hover-end:after,.ant-picker-cell-range-hover:after{right:0;left:2px}.ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover:before,.ant-picker-cell-in-view.ant-picker-cell-range-start.ant-picker-cell-range-hover:before,.ant-picker-cell-in-view.ant-picker-cell-range-end.ant-picker-cell-range-hover:before,.ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single).ant-picker-cell-range-hover-start:before,.ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single).ant-picker-cell-range-hover-end:before,.ant-picker-panel>:not(.ant-picker-date-panel) .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start:before,.ant-picker-panel>:not(.ant-picker-date-panel) .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end:before{background:#8cb8ff}.ant-picker-cell-in-view.ant-picker-cell-range-start:not(.ant-picker-cell-range-start-single):not(.ant-picker-cell-range-end) .ant-picker-cell-inner{border-radius:3px 0 0 3px}.ant-picker-cell-in-view.ant-picker-cell-range-end:not(.ant-picker-cell-range-end-single):not(.ant-picker-cell-range-start) .ant-picker-cell-inner{border-radius:0 3px 3px 0}.ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start .ant-picker-cell-inner:after,.ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end .ant-picker-cell-inner:after{position:absolute;top:0;bottom:0;z-index:-1;background:#8cb8ff;content:""}.ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start .ant-picker-cell-inner:after{right:-7px;left:0}.ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end .ant-picker-cell-inner:after{right:0;left:-7px}.ant-picker-cell-range-hover.ant-picker-cell-range-start:after{right:50%}.ant-picker-cell-range-hover.ant-picker-cell-range-end:after{left:50%}tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover:first-child:after,tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:first-child:after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-start:not(.ant-picker-cell-range-hover-edge-start-near-range):after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-start:after{left:6px;border-left:1px dashed #4088ff;border-top-left-radius:3px;border-bottom-left-radius:3px}tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover:last-child:after,tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child:after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-end:not(.ant-picker-cell-range-hover-edge-end-near-range):after,.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:after{right:6px;border-right:1px dashed #4088ff;border-top-right-radius:3px;border-bottom-right-radius:3px}.ant-picker-cell-disabled{pointer-events:none}.ant-picker-cell-disabled .ant-picker-cell-inner{color:#00000040;background:transparent}.ant-picker-cell-disabled:before{background:#f5f5f5}.ant-picker-cell-disabled.ant-picker-cell-today .ant-picker-cell-inner:before{border-color:#00000040}.ant-picker-decade-panel .ant-picker-content,.ant-picker-year-panel .ant-picker-content,.ant-picker-quarter-panel .ant-picker-content,.ant-picker-month-panel .ant-picker-content{height:264px}.ant-picker-decade-panel .ant-picker-cell-inner,.ant-picker-year-panel .ant-picker-cell-inner,.ant-picker-quarter-panel .ant-picker-cell-inner,.ant-picker-month-panel .ant-picker-cell-inner{padding:0 8px}.ant-picker-decade-panel .ant-picker-cell-disabled .ant-picker-cell-inner,.ant-picker-year-panel .ant-picker-cell-disabled .ant-picker-cell-inner,.ant-picker-quarter-panel .ant-picker-cell-disabled .ant-picker-cell-inner,.ant-picker-month-panel .ant-picker-cell-disabled .ant-picker-cell-inner{background:#f5f5f5}.ant-picker-quarter-panel .ant-picker-content{height:56px}.ant-picker-footer{line-height:38px;text-align:center;border-bottom:1px solid transparent}.ant-picker-panel .ant-picker-footer{border-top:1px solid #f0f0f0}.ant-picker-footer-extra{padding:0 12px;line-height:38px;text-align:left}.ant-picker-footer-extra:not(:last-child){border-bottom:1px solid #f0f0f0}.ant-picker-now{text-align:left}.ant-picker-today-btn{color:#0052d9}.ant-picker-today-btn:hover{color:#2575e6}.ant-picker-today-btn:active{color:#003eb3}.ant-picker-decade-panel .ant-picker-cell-inner{padding:0 4px}.ant-picker-decade-panel .ant-picker-cell:before{display:none}.ant-picker-year-panel .ant-picker-body,.ant-picker-quarter-panel .ant-picker-body,.ant-picker-month-panel .ant-picker-body{padding:0 8px}.ant-picker-year-panel .ant-picker-cell-inner,.ant-picker-quarter-panel .ant-picker-cell-inner,.ant-picker-month-panel .ant-picker-cell-inner{width:60px}.ant-picker-year-panel .ant-picker-cell-range-hover-start:after,.ant-picker-quarter-panel .ant-picker-cell-range-hover-start:after,.ant-picker-month-panel .ant-picker-cell-range-hover-start:after{left:14px;border-left:1px dashed #4088ff;border-radius:3px 0 0 3px}.ant-picker-panel-rtl .ant-picker-year-panel .ant-picker-cell-range-hover-start:after,.ant-picker-panel-rtl .ant-picker-quarter-panel .ant-picker-cell-range-hover-start:after,.ant-picker-panel-rtl .ant-picker-month-panel .ant-picker-cell-range-hover-start:after{right:14px;border-right:1px dashed #4088ff;border-radius:0 3px 3px 0}.ant-picker-year-panel .ant-picker-cell-range-hover-end:after,.ant-picker-quarter-panel .ant-picker-cell-range-hover-end:after,.ant-picker-month-panel .ant-picker-cell-range-hover-end:after{right:14px;border-right:1px dashed #4088ff;border-radius:0 3px 3px 0}.ant-picker-panel-rtl .ant-picker-year-panel .ant-picker-cell-range-hover-end:after,.ant-picker-panel-rtl .ant-picker-quarter-panel .ant-picker-cell-range-hover-end:after,.ant-picker-panel-rtl .ant-picker-month-panel .ant-picker-cell-range-hover-end:after{left:14px;border-left:1px dashed #4088ff;border-radius:3px 0 0 3px}.ant-picker-week-panel .ant-picker-body{padding:8px 12px}.ant-picker-week-panel .ant-picker-cell:hover .ant-picker-cell-inner,.ant-picker-week-panel .ant-picker-cell-selected .ant-picker-cell-inner,.ant-picker-week-panel .ant-picker-cell .ant-picker-cell-inner{background:transparent!important}.ant-picker-week-panel-row td{transition:background .3s}.ant-picker-week-panel-row:hover td{background:#f3f3f3}.ant-picker-week-panel-row-selected td,.ant-picker-week-panel-row-selected:hover td{background:#0052d9}.ant-picker-week-panel-row-selected td.ant-picker-cell-week,.ant-picker-week-panel-row-selected:hover td.ant-picker-cell-week{color:#ffffff80}.ant-picker-week-panel-row-selected td.ant-picker-cell-today .ant-picker-cell-inner:before,.ant-picker-week-panel-row-selected:hover td.ant-picker-cell-today .ant-picker-cell-inner:before{border-color:#fff}.ant-picker-week-panel-row-selected td .ant-picker-cell-inner,.ant-picker-week-panel-row-selected:hover td .ant-picker-cell-inner{color:#fff}.ant-picker-date-panel .ant-picker-body{padding:8px 12px}.ant-picker-date-panel .ant-picker-content{width:252px}.ant-picker-date-panel .ant-picker-content th{width:36px}.ant-picker-datetime-panel{display:flex}.ant-picker-datetime-panel .ant-picker-time-panel{border-left:1px solid #f0f0f0}.ant-picker-datetime-panel .ant-picker-date-panel,.ant-picker-datetime-panel .ant-picker-time-panel{transition:opacity .3s}.ant-picker-datetime-panel-active .ant-picker-date-panel,.ant-picker-datetime-panel-active .ant-picker-time-panel{opacity:.3}.ant-picker-datetime-panel-active .ant-picker-date-panel-active,.ant-picker-datetime-panel-active .ant-picker-time-panel-active{opacity:1}.ant-picker-time-panel{width:auto;min-width:auto}.ant-picker-time-panel .ant-picker-content{display:flex;flex:auto;height:224px}.ant-picker-time-panel-column{flex:1 0 auto;width:56px;margin:0;padding:0 0 194px;overflow-y:hidden;text-align:left;list-style:none;transition:background .3s}.ant-picker-time-panel-column:not(:first-child){border-left:1px solid #f0f0f0}.ant-picker-time-panel-column-active{background:rgba(224,235,255,.2)}.ant-picker-time-panel-column:hover{overflow-y:auto}.ant-picker-time-panel-column>li{margin:0;padding:0}.ant-picker-time-panel-column>li.ant-picker-time-panel-cell .ant-picker-time-panel-cell-inner{display:block;width:100%;height:28px;margin:0;padding:0;color:#000a29e6;line-height:28px;text-align:center;border-radius:0;cursor:pointer;transition:background .3s}.ant-picker-time-panel-column>li.ant-picker-time-panel-cell .ant-picker-time-panel-cell-inner:hover{background:#f3f3f3}.ant-picker-time-panel-column>li.ant-picker-time-panel-cell-selected .ant-picker-time-panel-cell-inner{background:#e0ebff}.ant-picker-time-panel-column>li.ant-picker-time-panel-cell-disabled .ant-picker-time-panel-cell-inner{color:#00000040;background:transparent;cursor:not-allowed}_:-ms-fullscreen .ant-picker-range-wrapper .ant-picker-month-panel .ant-picker-cell,:root .ant-picker-range-wrapper .ant-picker-month-panel .ant-picker-cell,_:-ms-fullscreen .ant-picker-range-wrapper .ant-picker-year-panel .ant-picker-cell,:root .ant-picker-range-wrapper .ant-picker-year-panel .ant-picker-cell{padding:21px 0}.ant-picker{box-sizing:border-box;margin:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";padding:4px 8px;position:relative;display:inline-flex;align-items:center;background:#fff;border:1px solid #d9d9d9;border-radius:3px;transition:border .3s,box-shadow .3s}.ant-picker:hover,.ant-picker-focused{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-picker:hover,.ant-input-rtl .ant-picker-focused{border-right-width:0;border-left-width:1px!important}.ant-picker-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-picker-focused{border-right-width:0;border-left-width:1px!important}.ant-picker.ant-picker-disabled{background:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-picker.ant-picker-disabled .ant-picker-suffix{color:#00000040}.ant-picker.ant-picker-borderless{background-color:transparent!important;border-color:transparent!important;box-shadow:none!important}.ant-picker-input{position:relative;display:inline-flex;width:100%}.ant-picker-input>input{position:relative;display:inline-block;width:100%;min-width:0;color:#000a29e6;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s;flex:auto;min-width:1px;height:auto;padding:0;background:transparent;border:0}.ant-picker-input>input::-moz-placeholder{opacity:1}.ant-picker-input>input::placeholder{color:#0006}.ant-picker-input>input:placeholder-shown{text-overflow:ellipsis}.ant-picker-input>input:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-picker-input>input:hover{border-right-width:0;border-left-width:1px!important}.ant-picker-input>input:focus,.ant-picker-input>input-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-picker-input>input:focus,.ant-input-rtl .ant-picker-input>input-focused{border-right-width:0;border-left-width:1px!important}.ant-picker-input>input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-picker-input>input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-picker-input>input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-picker-input>input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-picker-input>input{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-picker-input>input-lg{padding:6.5px 8px;font-size:16px}.ant-picker-input>input-md{padding:3px 7px;font-size:14px}.ant-picker-input>input-sm{padding:0 8px}.ant-picker-input>input-rtl{direction:rtl}.ant-picker-input>input:focus{box-shadow:none}.ant-picker-input>input[disabled]{background:transparent}.ant-picker-input:hover .ant-picker-clear{opacity:1}.ant-picker-large{padding:6.5px 8px}.ant-picker-large .ant-picker-input>input{font-size:16px}.ant-picker-small{padding:0 8px}.ant-picker-suffix{align-self:center;margin-left:4px;color:#00000040;pointer-events:none}.ant-picker-clear{position:absolute;top:50%;right:0;color:#00000040;background:#fff;transform:translateY(-50%);cursor:pointer;opacity:0;transition:opacity .3s,color .3s}.ant-picker-clear:hover{color:#000a2999}.ant-picker-separator{position:relative;display:inline-block;width:1em;height:16px;color:#00000040;font-size:16px;vertical-align:top;cursor:default}.ant-picker-focused .ant-picker-separator{color:#000a2999}.ant-picker-disabled .ant-picker-range-separator .ant-picker-separator{cursor:not-allowed}.ant-picker-range{position:relative;display:inline-flex}.ant-picker-range .ant-picker-clear{right:8px}.ant-picker-range:hover .ant-picker-clear{opacity:1}.ant-picker-range .ant-picker-active-bar{bottom:-1px;height:2px;margin-left:8px;background:#0052d9;opacity:0;transition:all .3s ease-out;pointer-events:none}.ant-picker-range.ant-picker-focused .ant-picker-active-bar{opacity:1}.ant-picker-range-separator{align-items:center;padding:0 8px;line-height:1}.ant-picker-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;z-index:1050}.ant-picker-dropdown-hidden{display:none}.ant-picker-dropdown-placement-bottomLeft .ant-picker-range-arrow{top:1.66666667px;display:block;transform:rotate(-45deg)}.ant-picker-dropdown-placement-topLeft .ant-picker-range-arrow{bottom:1.66666667px;display:block;transform:rotate(135deg)}.ant-picker-dropdown-range{padding:6.66666667px 0}.ant-picker-dropdown-range-hidden{display:none}.ant-picker-dropdown .ant-picker-panel>.ant-picker-time-panel{padding-top:4px}.ant-picker-ranges{margin-bottom:0;padding:4px 12px;overflow:hidden;line-height:34px;text-align:left;list-style:none}.ant-picker-ranges>li{display:inline-block}.ant-picker-ranges .ant-picker-preset>.ant-tag-blue{color:#0052d9;background:#e6f4ff;border-color:#7abaff;cursor:pointer}.ant-picker-ranges .ant-picker-ok{float:right;margin-left:8px}.ant-picker-range-wrapper{display:flex}.ant-picker-range-arrow{position:absolute;z-index:1;display:none;width:10px;height:10px;margin-left:12px;box-shadow:2px -2px 6px #0000000f;transition:left .3s ease-out}.ant-picker-range-arrow:after{position:absolute;top:1px;right:1px;width:10px;height:10px;border:5px solid #f0f0f0;border-color:#fff #fff transparent transparent;content:""}.ant-picker-panel-container{overflow:hidden;vertical-align:top;background:#fff;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d;transition:margin .3s}.ant-picker-panel-container .ant-picker-panels{display:inline-flex;flex-wrap:nowrap;direction:ltr}.ant-picker-panel-container .ant-picker-panel{vertical-align:top;background:transparent;border-width:0 0 1px 0;border-radius:0}.ant-picker-panel-container .ant-picker-panel-focused{border-color:#f0f0f0}.ant-picker-rtl{direction:rtl}.ant-picker-rtl .ant-picker-suffix{margin-right:4px;margin-left:0}.ant-picker-rtl .ant-picker-clear{right:auto;left:0}.ant-picker-rtl .ant-picker-separator{transform:rotate(180deg)}.ant-picker-panel-rtl .ant-picker-header-view button:not(:first-child){margin-right:8px;margin-left:0}.ant-picker-rtl.ant-picker-range .ant-picker-clear{right:auto;left:8px}.ant-picker-rtl.ant-picker-range .ant-picker-active-bar{margin-right:8px;margin-left:0}.ant-picker-dropdown-rtl .ant-picker-ranges{text-align:right}.ant-picker-dropdown-rtl .ant-picker-ranges .ant-picker-ok{float:left;margin-right:8px;margin-left:0}.ant-picker-panel-rtl{direction:rtl}.ant-picker-panel-rtl .ant-picker-prev-icon,.ant-picker-panel-rtl .ant-picker-super-prev-icon{transform:rotate(135deg)}.ant-picker-panel-rtl .ant-picker-next-icon,.ant-picker-panel-rtl .ant-picker-super-next-icon{transform:rotate(-45deg)}.ant-picker-cell .ant-picker-cell-inner{position:relative;z-index:2;display:inline-block;min-width:24px;height:24px;line-height:24px;border-radius:3px;transition:background .3s,border .3s}.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-start:before{right:50%;left:0}.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-end:before{right:0;left:50%}.ant-picker-panel-rtl .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-start .ant-picker-cell-inner:after{right:0;left:-7px}.ant-picker-panel-rtl .ant-picker-date-panel .ant-picker-cell-in-view.ant-picker-cell-in-range.ant-picker-cell-range-hover-end .ant-picker-cell-inner:after{right:-7px;left:0}.ant-picker-panel-rtl .ant-picker-cell-range-hover.ant-picker-cell-range-start:after{right:0;left:50%}.ant-picker-panel-rtl .ant-picker-cell-range-hover.ant-picker-cell-range-end:after{right:50%;left:0}.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover:first-child:after,.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:first-child:after,.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-start:not(.ant-picker-cell-range-hover-edge-start-near-range):after,.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:after{right:6px;left:0;border-right:1px dashed #4088ff;border-left:none;border-radius:0 3px 3px 0}.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover:last-child:after,.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child:after,.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-hover-edge-end:not(.ant-picker-cell-range-hover-edge-end-near-range):after,.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-hover-end:after{right:0;left:6px;border-right:none;border-left:1px dashed #4088ff;border-radius:3px 0 0 3px}.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child:after,.ant-picker-panel-rtl .ant-picker-cell-in-view.ant-picker-cell-range-hover-start.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:after{right:6px;border-right:1px dashed #4088ff;border-top-right-radius:3px;border-bottom-right-radius:3px}.ant-picker-panel-rtl tr>.ant-picker-cell-in-view.ant-picker-cell-range-hover-end:first-child:after{left:6px;border-left:1px dashed #4088ff;border-top-left-radius:3px;border-bottom-left-radius:3px}.ant-picker-panel-rtl .ant-picker-time-panel{direction:ltr}.ant-descriptions-title{margin-bottom:20px;color:#000a29e6;font-weight:700;font-size:16px;line-height:1.5715}.ant-descriptions-view{width:100%;overflow:hidden;border-radius:3px}.ant-descriptions-view table{width:100%;table-layout:fixed}.ant-descriptions-row>th,.ant-descriptions-row>td{padding-bottom:16px}.ant-descriptions-row:last-child{border-bottom:none}.ant-descriptions-item-label{color:#000a29e6;font-weight:400;font-size:14px;line-height:1.5715}.ant-descriptions-item-label:after{position:relative;top:-.5px;margin:0 8px 0 2px;content:" "}.ant-descriptions-item-colon:after{content:":"}.ant-descriptions-item-no-label:after{margin:0;content:""}.ant-descriptions-item-content{display:table-cell;color:#000a29e6;font-size:14px;line-height:1.5715}.ant-descriptions-item{padding-bottom:0}.ant-descriptions-item>span{display:inline-block}.ant-descriptions-middle .ant-descriptions-row>th,.ant-descriptions-middle .ant-descriptions-row>td{padding-bottom:12px}.ant-descriptions-small .ant-descriptions-row>th,.ant-descriptions-small .ant-descriptions-row>td{padding-bottom:8px}.ant-descriptions-bordered .ant-descriptions-view{border:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-view>table{table-layout:auto}.ant-descriptions-bordered .ant-descriptions-item-label,.ant-descriptions-bordered .ant-descriptions-item-content{padding:16px 24px;border-right:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-item-label:last-child,.ant-descriptions-bordered .ant-descriptions-item-content:last-child{border-right:none}.ant-descriptions-bordered .ant-descriptions-item-label{background-color:#fafafa}.ant-descriptions-bordered .ant-descriptions-item-label:after{display:none}.ant-descriptions-bordered .ant-descriptions-row{border-bottom:1px solid #f0f0f0}.ant-descriptions-bordered .ant-descriptions-row:last-child{border-bottom:none}.ant-descriptions-bordered.ant-descriptions-middle .ant-descriptions-item-label,.ant-descriptions-bordered.ant-descriptions-middle .ant-descriptions-item-content{padding:12px 24px}.ant-descriptions-bordered.ant-descriptions-small .ant-descriptions-item-label,.ant-descriptions-bordered.ant-descriptions-small .ant-descriptions-item-content{padding:8px 16px}.ant-descriptions-rtl{direction:rtl}.ant-descriptions-rtl .ant-descriptions-item-label:after{margin:0 2px 0 8px}.ant-divider{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";border-top:1px solid #f0f0f0}.ant-divider-vertical{position:relative;top:-.06em;display:inline-block;height:.9em;margin:0 8px;vertical-align:middle;border-top:0;border-left:1px solid #f0f0f0}.ant-divider-horizontal{display:flex;clear:both;width:100%;min-width:100%;margin:24px 0}.ant-divider-horizontal.ant-divider-with-text{display:flex;margin:16px 0;color:#000a29e6;font-weight:500;font-size:16px;white-space:nowrap;text-align:center;border-top:0}.ant-divider-horizontal.ant-divider-with-text:before,.ant-divider-horizontal.ant-divider-with-text:after{position:relative;top:50%;width:50%;border-top:1px solid #f0f0f0;transform:translateY(50%);content:""}.ant-divider-horizontal.ant-divider-with-text-left:before{top:50%;width:5%}.ant-divider-horizontal.ant-divider-with-text-left:after{top:50%;width:95%}.ant-divider-horizontal.ant-divider-with-text-right:before{top:50%;width:95%}.ant-divider-horizontal.ant-divider-with-text-right:after{top:50%;width:5%}.ant-divider-inner-text{display:inline-block;padding:0 1em}.ant-divider-dashed{background:none;border-color:#f0f0f0;border-style:dashed;border-width:1px 0 0}.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed{border-top:0}.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed:before,.ant-divider-horizontal.ant-divider-with-text.ant-divider-dashed:after{border-style:dashed none none}.ant-divider-vertical.ant-divider-dashed{border-width:0 0 0 1px}.ant-divider-plain.ant-divider-with-text{color:#000a29e6;font-weight:400;font-size:14px}.ant-divider-rtl{direction:rtl}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-left:before{width:95%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-left:after{width:5%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-right:before{width:5%}.ant-divider-rtl.ant-divider-horizontal.ant-divider-with-text-right:after{width:95%}.ant-drawer{position:fixed;z-index:1000;width:0%;height:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1),height 0s ease .3s,width 0s ease .3s}.ant-drawer>*{transition:transform .3s cubic-bezier(.7,.3,.1,1),box-shadow .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-content-wrapper{position:absolute;width:100%;height:100%}.ant-drawer .ant-drawer-content{width:100%;height:100%}.ant-drawer-left,.ant-drawer-right{top:0;width:0%;height:100%}.ant-drawer-left .ant-drawer-content-wrapper,.ant-drawer-right .ant-drawer-content-wrapper{height:100%}.ant-drawer-left.ant-drawer-open,.ant-drawer-right.ant-drawer-open{width:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-left,.ant-drawer-left .ant-drawer-content-wrapper{left:0}.ant-drawer-left.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:-4px 0 14px #0000001a,0 0 2px #00000026}.ant-drawer-right,.ant-drawer-right .ant-drawer-content-wrapper{right:0}.ant-drawer-right.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:-4px 0 14px #0000001a,0 0 2px #00000026}.ant-drawer-right.ant-drawer-open.no-mask{right:1px;transform:translate(1px)}.ant-drawer-top,.ant-drawer-bottom{left:0;width:100%;height:0%}.ant-drawer-top .ant-drawer-content-wrapper,.ant-drawer-bottom .ant-drawer-content-wrapper{width:100%}.ant-drawer-top.ant-drawer-open,.ant-drawer-bottom.ant-drawer-open{height:100%;transition:transform .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-top{top:0}.ant-drawer-top.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:-4px 0 14px #0000001a,0 0 2px #00000026}.ant-drawer-bottom,.ant-drawer-bottom .ant-drawer-content-wrapper{bottom:0}.ant-drawer-bottom.ant-drawer-open .ant-drawer-content-wrapper{box-shadow:-4px 0 14px #0000001a,0 0 2px #00000026}.ant-drawer-bottom.ant-drawer-open.no-mask{bottom:1px;transform:translateY(1px)}.ant-drawer.ant-drawer-open .ant-drawer-mask{height:100%;opacity:1;transition:none;animation:antdDrawerFadeIn .3s cubic-bezier(.7,.3,.1,1)}.ant-drawer-title{margin:0;color:#000a29e6;font-weight:600;font-size:18px;line-height:25px}.ant-drawer-fullscreen{position:absolute;top:25px;right:24px;color:#606c80;cursor:pointer;transition:color .3s}.ant-drawer-fullscreen>.anticon{margin-right:4px}.ant-drawer-fullscreen:hover{color:#202d40}.ant-drawer-content{position:relative;z-index:1;background-color:#fff;background-clip:padding-box;border:0}.ant-drawer-close{position:absolute;top:26px;left:-10px;z-index:10;display:block;width:20px;height:20px;color:#f5f7fa;font-weight:700;font-size:12px;font-style:normal;line-height:1;text-align:center;text-transform:none;text-decoration:none;background:#adbacc;border:0;border-radius:50%;outline:0;box-shadow:0 0 2px #00000014,0 2px 6px #00000014;cursor:pointer;transition:all .3s;text-rendering:auto}.ant-drawer-close:focus,.ant-drawer-close:hover{text-decoration:none;background-color:#8592a6}.ant-drawer-header-no-title .ant-drawer-close{margin-right:var(--scroll-bar);padding-right:calc(4px - var(--scroll-bar))}.ant-drawer-header{position:relative;padding:16px 24px;color:#000a29e6;background:#fff;border-radius:3px 3px 0 0}.ant-drawer-header-no-title{color:#000a29e6;background:#fff}.ant-drawer-wrapper-body{display:flex;flex-direction:column;flex-wrap:nowrap;width:100%;height:100%}.ant-drawer-body{flex-grow:1;padding:24px;overflow:auto;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-drawer-footer{flex-shrink:0;padding:28px}.ant-drawer-mask{position:absolute;top:0;left:0;width:100%;height:0;background-color:#000a2999;opacity:0;filter:alpha(opacity=45);transition:opacity .3s linear,height 0s ease .3s}.ant-drawer-open-content{box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-drawer .ant-picker-clear{background:#fff}@keyframes antdDrawerFadeIn{0%{opacity:0}to{opacity:1}}.ant-drawer-rtl{direction:rtl}.ant-drawer-rtl .ant-drawer-close{right:auto;left:0}.ant-drawer-header{border-bottom:1px solid #e4e5eb;padding:16px}.ant-drawer-body{padding:16px}.ant-drawer-close{width:24px;height:24px;top:16px!important;left:unset!important;right:16px!important;bottom:unset!important;border-radius:3px;color:#000a29e6;background-color:transparent;box-shadow:none}.ant-drawer-close:hover{background-color:#f1f2f5}.ant-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:-9999px;left:-9999px;z-index:1050;display:block}.ant-dropdown:before{position:absolute;top:-7px;right:0;bottom:-7px;left:-7px;z-index:-9999;opacity:.0001;content:" "}.ant-dropdown-wrap{position:relative}.ant-dropdown-wrap .ant-btn>.anticon-down{display:inline-block;font-size:10px}.ant-dropdown-wrap .anticon-down:before{transition:transform .2s}.ant-dropdown-wrap-open .anticon-down:before{transform:rotate(180deg)}.ant-dropdown-hidden,.ant-dropdown-menu-hidden{display:none}.ant-dropdown-menu{position:relative;margin:0;padding:4px 0;text-align:left;list-style-type:none;background-color:#fff;background-clip:padding-box;border-radius:3px;outline:none;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d;-webkit-transform:translate3d(0,0,0)}.ant-dropdown-menu-item-group-title{padding:5px 8px;color:#000a2999;transition:all .3s}.ant-dropdown-menu-submenu-popup{position:absolute;z-index:1050;background:transparent;box-shadow:none}.ant-dropdown-menu-submenu-popup>.ant-dropdown-menu{transform-origin:0 0}.ant-dropdown-menu-submenu-popup ul,.ant-dropdown-menu-submenu-popup li{list-style:none}.ant-dropdown-menu-submenu-popup ul{margin-right:.3em;margin-left:.3em}.ant-dropdown-menu-item,.ant-dropdown-menu-submenu-title{clear:both;margin:0;padding:5px 8px;color:#000a29e6;font-weight:400;font-size:14px;line-height:22px;white-space:nowrap;cursor:pointer;transition:all .3s}.ant-dropdown-menu-item>.anticon:first-child,.ant-dropdown-menu-submenu-title>.anticon:first-child,.ant-dropdown-menu-item>span>.anticon:first-child,.ant-dropdown-menu-submenu-title>span>.anticon:first-child{min-width:12px;margin-right:8px;font-size:12px}.ant-dropdown-menu-item>a,.ant-dropdown-menu-submenu-title>a{display:block;margin:-5px -8px;padding:5px 8px;color:#000a29e6;transition:all .3s}.ant-dropdown-menu-item>a:hover,.ant-dropdown-menu-submenu-title>a:hover{color:#000a29e6}.ant-dropdown-menu-item-selected,.ant-dropdown-menu-submenu-title-selected,.ant-dropdown-menu-item-selected>a,.ant-dropdown-menu-submenu-title-selected>a{color:#0052d9;background-color:#e0ebff}.ant-dropdown-menu-item:hover,.ant-dropdown-menu-submenu-title:hover{background-color:#f3f3f3}.ant-dropdown-menu-item-disabled,.ant-dropdown-menu-submenu-title-disabled{color:#00000040;cursor:not-allowed}.ant-dropdown-menu-item-disabled:hover,.ant-dropdown-menu-submenu-title-disabled:hover{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-dropdown-menu-item-divider,.ant-dropdown-menu-submenu-title-divider{height:1px;margin:4px 0;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow,.ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow{position:absolute;right:8px}.ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow-icon,.ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{margin-right:0!important;color:#000a2999;font-style:normal;display:inline-block;font-size:10px}.ant-dropdown-menu-item-group-list{margin:0 8px;padding:0;list-style:none}.ant-dropdown-menu-submenu-title{padding-right:20px}.ant-dropdown-menu-submenu-vertical{position:relative}.ant-dropdown-menu-submenu-vertical>.ant-dropdown-menu{position:absolute;top:0;left:100%;min-width:100%;margin-left:4px;transform-origin:0 0}.ant-dropdown-menu-submenu.ant-dropdown-menu-submenu-disabled .ant-dropdown-menu-submenu-title,.ant-dropdown-menu-submenu.ant-dropdown-menu-submenu-disabled .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-dropdown-menu-submenu-selected .ant-dropdown-menu-submenu-title{color:#0052d9}.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-enter.slide-down-enter-active.ant-dropdown-placement-bottomRight,.ant-dropdown.slide-down-appear.slide-down-appear-active.ant-dropdown-placement-bottomRight{animation-name:antSlideUpIn}.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-enter.slide-up-enter-active.ant-dropdown-placement-topRight,.ant-dropdown.slide-up-appear.slide-up-appear-active.ant-dropdown-placement-topRight{animation-name:antSlideDownIn}.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomLeft,.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomCenter,.ant-dropdown.slide-down-leave.slide-down-leave-active.ant-dropdown-placement-bottomRight{animation-name:antSlideUpOut}.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topLeft,.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topCenter,.ant-dropdown.slide-up-leave.slide-up-leave-active.ant-dropdown-placement-topRight{animation-name:antSlideDownOut}.ant-dropdown-trigger>.anticon.anticon-down,.ant-dropdown-link>.anticon.anticon-down{display:inline-block;font-size:10px}.ant-dropdown-button{white-space:nowrap}.ant-dropdown-button.ant-btn-group>.ant-btn:last-child:not(:first-child):not(.ant-btn-icon-only){padding-right:8px;padding-left:8px}.ant-dropdown-button .anticon.anticon-down{display:inline-block;font-size:10px}.ant-dropdown-menu-dark,.ant-dropdown-menu-dark .ant-dropdown-menu{background:#001529}.ant-dropdown-menu-dark .ant-dropdown-menu-item,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a{color:#ffffffa6}.ant-dropdown-menu-dark .ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow:after,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow:after,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a .ant-dropdown-menu-submenu-arrow:after{color:#ffffffa6}.ant-dropdown-menu-dark .ant-dropdown-menu-item:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-submenu-title:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-item>a:hover{color:#fff;background:transparent}.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected,.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected:hover,.ant-dropdown-menu-dark .ant-dropdown-menu-item-selected>a{color:#fff;background:#0052d9}.ant-dropdown-rtl{direction:rtl}.ant-dropdown-rtl.ant-dropdown:before{right:-7px;left:0}.ant-dropdown-rtl .ant-dropdown-menu-item-group-title{direction:rtl;text-align:right}.ant-dropdown-rtl .ant-dropdown-menu-submenu-popup ul,.ant-dropdown-rtl .ant-dropdown-menu-submenu-popup li,.ant-dropdown-rtl .ant-dropdown-menu-item,.ant-dropdown-rtl .ant-dropdown-menu-submenu-title{text-align:right}.ant-dropdown-menu-item>.anticon:first-child,.ant-dropdown-menu-submenu-title>.anticon:first-child,.ant-dropdown-menu-item>span>.anticon:first-child,.ant-dropdown-menu-submenu-title>span>.anticon:first-child{min-width:14px;font-size:14px}.ant-dropdown-rtl .ant-dropdown-menu-item>.anticon:first-child,.ant-dropdown-rtl .ant-dropdown-menu-submenu-title>.anticon:first-child,.ant-dropdown-rtl .ant-dropdown-menu-item>span>.anticon:first-child,.ant-dropdown-rtl .ant-dropdown-menu-submenu-title>span>.anticon:first-child{margin-right:0;margin-left:8px}.ant-dropdown-rtl .ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow,.ant-dropdown-rtl .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow{right:auto;left:8px}.ant-dropdown-rtl .ant-dropdown-menu-item .ant-dropdown-menu-submenu-arrow-icon,.ant-dropdown-rtl .ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-arrow-icon{margin-left:0!important;transform:scaleX(-1)}.ant-dropdown-rtl .ant-dropdown-menu-submenu-title{padding-right:8px;padding-left:20px}.ant-dropdown-rtl .ant-dropdown-menu-submenu-vertical>.ant-dropdown-menu{right:100%;left:0;margin-right:4px;margin-left:0}.ant-empty{margin:0 8px;font-size:14px;line-height:1.5715;text-align:center}.ant-empty-image{height:100px;margin-bottom:20px}.ant-empty-image img{height:100%}.ant-empty-image svg{height:100%;margin:auto}.ant-empty-description{margin:0;color:#8592a6}.ant-empty-footer{margin-top:24px}.ant-empty-normal{margin:32px 0;color:#adbacc}.ant-empty-normal .ant-empty-image{height:40px}.ant-empty-horizontal{display:flex;align-items:center;justify-content:center}.ant-empty-horizontal .ant-empty-image{height:22px;margin-right:8px;margin-bottom:0;color:#adbacc;font-size:20px;line-height:22px}.ant-empty-horizontal .ant-empty-description{color:#adbacc}.ant-empty-small{margin:8px 0;color:#adbacc}.ant-empty-small .ant-empty-image{height:35px}.ant-empty-img-default-ellipse{fill-opacity:.8;fill:#f5f5f5}.ant-empty-img-default-path-1{fill:#aeb8c2}.ant-empty-img-default-path-2{fill:url(#linearGradient-1)}.ant-empty-img-default-path-3{fill:#f5f5f7}.ant-empty-img-default-path-4,.ant-empty-img-default-path-5{fill:#dce0e6}.ant-empty-img-default-g{fill:#fff}.ant-empty-img-simple-ellipse{fill:#f5f5f5}.ant-empty-img-simple-g{stroke:#d9d9d9}.ant-empty-img-simple-path{fill:#fafafa}.ant-empty-rtl{direction:rtl}.ant-form-item .ant-mentions,.ant-form-item textarea.ant-input{height:auto}.ant-form-item .ant-upload{background:transparent}.ant-form-item .ant-upload.ant-upload-drag{background:#f1f2f5}.ant-form-item input[type=radio],.ant-form-item input[type=checkbox]{width:14px;height:14px}.ant-form-item .ant-radio-inline,.ant-form-item .ant-checkbox-inline{display:inline-block;margin-left:8px;font-weight:400;vertical-align:middle;cursor:pointer}.ant-form-item .ant-radio-inline:first-child,.ant-form-item .ant-checkbox-inline:first-child{margin-left:0}.ant-form-item .ant-checkbox-vertical,.ant-form-item .ant-radio-vertical{display:block}.ant-form-item .ant-checkbox-vertical+.ant-checkbox-vertical,.ant-form-item .ant-radio-vertical+.ant-radio-vertical{margin-left:0}.ant-form-item .ant-input-number+.ant-form-text{margin-left:8px}.ant-form-item .ant-input-number-handler-wrap{z-index:2}.ant-form-item .ant-select,.ant-form-item .ant-cascader-picker{width:100%}.ant-form-item .ant-input-group .ant-select,.ant-form-item .ant-input-group .ant-cascader-picker{width:auto}.ant-form-inline{display:flex;flex-wrap:wrap}.ant-form-inline .ant-form-item{flex:none;flex-wrap:nowrap;margin-right:16px;margin-bottom:0}.ant-form-inline .ant-form-item-with-help{margin-bottom:24px}.ant-form-inline .ant-form-item>.ant-form-item-label,.ant-form-inline .ant-form-item>.ant-form-item-control{display:inline-block;vertical-align:top}.ant-form-inline .ant-form-item .ant-form-text,.ant-form-inline .ant-form-item .ant-form-item-has-feedback{display:inline-block}.ant-form-horizontal .ant-form-item-label{flex-grow:0}.ant-form-horizontal .ant-form-item-control{flex:1 1 0}.ant-form-vertical .ant-form-item{flex-direction:column}.ant-form-vertical .ant-form-item-label>label{height:auto}.ant-form-vertical .ant-form-item-label,.ant-col-24.ant-form-item-label,.ant-col-xl-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-form-vertical .ant-form-item-label>label,.ant-col-24.ant-form-item-label>label,.ant-col-xl-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-form-vertical .ant-form-item-label,.ant-form-rtl.ant-col-24.ant-form-item-label,.ant-form-rtl.ant-col-xl-24.ant-form-item-label{text-align:right}@media (max-width: 575px){.ant-form-item .ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-form-item .ant-form-item-label>label{margin:0}.ant-form-rtl.ant-form-item .ant-form-item-label{text-align:right}.ant-form .ant-form-item{flex-wrap:wrap}.ant-form .ant-form-item .ant-form-item-label,.ant-form .ant-form-item .ant-form-item-control{flex:0 0 100%;max-width:100%}.ant-col-xs-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-xs-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-col-xs-24.ant-form-item-label{text-align:right}}@media (max-width: 767px){.ant-col-sm-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-sm-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-col-sm-24.ant-form-item-label{text-align:right}}@media (max-width: 991px){.ant-col-md-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-md-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-col-md-24.ant-form-item-label{text-align:right}}@media (max-width: 1199px){.ant-col-lg-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-lg-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-col-lg-24.ant-form-item-label{text-align:right}}@media (max-width: 1599px){.ant-col-xl-24.ant-form-item-label{margin:0;padding:0 0 8px;line-height:1.5715;white-space:initial;text-align:left}.ant-col-xl-24.ant-form-item-label>label{margin:0}.ant-form-rtl.ant-col-xl-24.ant-form-item-label{text-align:right}}.ant-form-item-has-feedback .ant-input{padding-right:24px}.ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input-suffix{padding-right:18px}.ant-form-item-has-feedback .ant-input-search:not(.ant-input-search-enter-button) .ant-input-suffix{right:28px}.ant-form-item-has-feedback .ant-switch{margin:2px 0 4px}.ant-form-item-has-feedback>.ant-select .ant-select-arrow,.ant-form-item-has-feedback>.ant-select .ant-select-selection__clear,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-arrow,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection__clear{right:28px}.ant-form-item-has-feedback>.ant-select .ant-select-selection-selected-value,.ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection-selected-value{padding-right:42px}.ant-form-item-has-feedback .ant-cascader-picker-arrow{margin-right:17px}.ant-form-item-has-feedback .ant-cascader-picker-clear{right:28px}.ant-form-item-has-feedback .ant-picker,.ant-form-item-has-feedback .ant-picker-large,.ant-form-item-has-feedback .ant-picker-small{padding-right:26.2px}.ant-form-item-has-feedback.ant-form-item-has-success .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-has-warning .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-has-error .ant-form-item-children-icon,.ant-form-item-has-feedback.ant-form-item-is-validating .ant-form-item-children-icon{position:absolute;top:50%;right:0;z-index:1;width:32px;height:20px;margin-top:-10px;font-size:16px;line-height:20px;text-align:center;visibility:visible;animation:zoomIn .3s cubic-bezier(.12,.4,.29,1.46);pointer-events:none}.ant-form-item-has-feedback.ant-form-item-has-success .ant-form-item-children-icon svg,.ant-form-item-has-feedback.ant-form-item-has-warning .ant-form-item-children-icon svg,.ant-form-item-has-feedback.ant-form-item-has-error .ant-form-item-children-icon svg,.ant-form-item-has-feedback.ant-form-item-is-validating .ant-form-item-children-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-form-item-has-success.ant-form-item-has-feedback .ant-form-item-children-icon{color:#00a870;animation-name:diffZoomIn1!important}.ant-form-item-has-warning .ant-form-item-explain,.ant-form-item-has-warning .ant-form-item-split{color:#f9e0c7}.ant-form-item-has-warning .ant-input,.ant-form-item-has-warning .ant-input-affix-wrapper,.ant-form-item-has-warning .ant-input:hover,.ant-form-item-has-warning .ant-input-affix-wrapper:hover{background-color:#fff;border-color:#f9e0c7}.ant-form-item-has-warning .ant-input:focus,.ant-form-item-has-warning .ant-input-affix-wrapper:focus,.ant-form-item-has-warning .ant-input-focused,.ant-form-item-has-warning .ant-input-affix-wrapper-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #f9e0c733}.ant-form-item-has-warning .ant-input:not([disabled]):hover,.ant-form-item-has-warning .ant-input-affix-wrapper:not([disabled]):hover{border-color:#f9e0c7}.ant-form-item-has-warning .ant-input-affix-wrapper input:focus{box-shadow:none!important}.ant-form-item-has-warning .ant-calendar-picker-open .ant-calendar-picker-input{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #f9e0c733}.ant-form-item-has-warning .ant-input-prefix{color:#f9e0c7}.ant-form-item-has-warning .ant-input-group-addon{color:#f9e0c7;background-color:#fff;border-color:#f9e0c7}.ant-form-item-has-warning .has-feedback{color:#f9e0c7}.ant-form-item-has-warning.ant-form-item-has-feedback .ant-form-item-children-icon{color:#f9e0c7;animation-name:diffZoomIn3!important}.ant-form-item-has-warning .ant-select:not(.ant-select-borderless) .ant-select-selector{border-color:#f9e0c7!important}.ant-form-item-has-warning .ant-select:not(.ant-select-borderless).ant-select-open .ant-select-selector,.ant-form-item-has-warning .ant-select:not(.ant-select-borderless).ant-select-focused .ant-select-selector{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #f9e0c733}.ant-form-item-has-warning .ant-input-number,.ant-form-item-has-warning .ant-picker{border-color:#f9e0c7}.ant-form-item-has-warning .ant-input-number-focused,.ant-form-item-has-warning .ant-picker-focused,.ant-form-item-has-warning .ant-input-number:focus,.ant-form-item-has-warning .ant-picker:focus{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #f9e0c733}.ant-form-item-has-warning .ant-input-number:not([disabled]):hover,.ant-form-item-has-warning .ant-picker:not([disabled]):hover{border-color:#f9e0c7}.ant-form-item-has-warning .ant-cascader-picker:focus .ant-cascader-input{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #f9e0c733}.ant-form-item-has-error .ant-form-item-explain,.ant-form-item-has-error .ant-form-item-split{color:#e34d59}.ant-form-item-has-error .ant-input,.ant-form-item-has-error .ant-input-affix-wrapper,.ant-form-item-has-error .ant-input:hover,.ant-form-item-has-error .ant-input-affix-wrapper:hover{background-color:#fff;border-color:#e34d59}.ant-form-item-has-error .ant-input:focus,.ant-form-item-has-error .ant-input-affix-wrapper:focus,.ant-form-item-has-error .ant-input-focused,.ant-form-item-has-error .ant-input-affix-wrapper-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-input:not([disabled]):hover,.ant-form-item-has-error .ant-input-affix-wrapper:not([disabled]):hover{border-color:#e34d59}.ant-form-item-has-error .ant-input-affix-wrapper input:focus{box-shadow:none!important}.ant-form-item-has-error .ant-calendar-picker-open .ant-calendar-picker-input{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-input-prefix{color:#e34d59}.ant-form-item-has-error .ant-input-group-addon{color:#e34d59;background-color:#fff;border-color:#e34d59}.ant-form-item-has-error .has-feedback{color:#e34d59}.ant-form-item-has-error.ant-form-item-has-feedback .ant-form-item-children-icon{color:#e34d59;animation-name:diffZoomIn2!important}.ant-form-item-has-error .ant-select:not(.ant-select-borderless) .ant-select-selector{border-color:#e34d59!important}.ant-form-item-has-error .ant-select:not(.ant-select-borderless).ant-select-open .ant-select-selector,.ant-form-item-has-error .ant-select:not(.ant-select-borderless).ant-select-focused .ant-select-selector{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-input-group-addon .ant-select.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{border:0}.ant-form-item-has-error .ant-select.ant-select-auto-complete .ant-input:focus{border-color:#e34d59}.ant-form-item-has-error .ant-input-number,.ant-form-item-has-error .ant-picker{border-color:#e34d59}.ant-form-item-has-error .ant-input-number-focused,.ant-form-item-has-error .ant-picker-focused,.ant-form-item-has-error .ant-input-number:focus,.ant-form-item-has-error .ant-picker:focus{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-input-number:not([disabled]):hover,.ant-form-item-has-error .ant-picker:not([disabled]):hover{border-color:#e34d59}.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor,.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor:not([disabled]):hover{border-color:#e34d59}.ant-form-item-has-error .ant-mention-wrapper.ant-mention-active:not([disabled]) .ant-mention-editor,.ant-form-item-has-error .ant-mention-wrapper .ant-mention-editor:not([disabled]):focus{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-cascader-picker:focus .ant-cascader-input{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #e34d5933}.ant-form-item-has-error .ant-transfer-list{border-color:#e34d59}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]){border-color:#d9d9d9}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]):hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-form-item-has-error .ant-transfer-list-search:not([disabled]):hover{border-right-width:0;border-left-width:1px!important}.ant-form-item-has-error .ant-transfer-list-search:not([disabled]):focus{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-form-item-has-error .ant-transfer-list-search:not([disabled]):focus{border-right-width:0;border-left-width:1px!important}.ant-form-item-has-error-leave .ant-form-item-explain{color:#e34d59}.ant-form-item-is-validating.ant-form-item-has-feedback .ant-form-item-children-icon{display:inline-block;color:#0052d9}.ant-form{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum"}.ant-form legend{display:block;width:100%;margin-bottom:20px;padding:0;color:#000a2999;font-size:16px;line-height:inherit;border:0;border-bottom:1px solid #d9d9d9}.ant-form label{font-size:14px}.ant-form input[type=search]{box-sizing:border-box}.ant-form input[type=radio],.ant-form input[type=checkbox]{line-height:normal}.ant-form input[type=file]{display:block}.ant-form input[type=range]{display:block;width:100%}.ant-form select[multiple],.ant-form select[size]{height:auto}.ant-form input[type=file]:focus,.ant-form input[type=radio]:focus,.ant-form input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.ant-form output{display:block;padding-top:15px;color:#000a29e6;font-size:14px;line-height:1.5715}.ant-form .ant-form-text{display:inline-block;padding-right:8px}.ant-form-small .ant-form-item-label>label{height:24px}.ant-form-small .ant-form-item-control-input{min-height:24px}.ant-form-large .ant-form-item-label>label{height:40px}.ant-form-large .ant-form-item-control-input{min-height:40px}.ant-form-item{box-sizing:border-box;margin:0 0 24px;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";vertical-align:top}.ant-form-item-label{display:inline-block;flex-grow:0;overflow:hidden;white-space:nowrap;text-align:right;vertical-align:middle}.ant-form-item-label-left{text-align:left}.ant-form-item-label>label{position:relative;display:inline-flex;align-items:center;height:32px;color:#000a29e6;font-size:14px}.ant-form-item-label>label>.anticon{font-size:14px;vertical-align:top}.ant-form-item-label>label.ant-form-item-required:after{display:inline-block;margin-left:2px;color:#e34d59;font-size:14px;font-family:SimSun,sans-serif;line-height:1;content:"*"}.ant-form-hide-required-mark .ant-form-item-label>label.ant-form-item-required:after{display:none}.ant-form-item-tooltip{margin-left:4px;color:#adbacc;font-size:14px;cursor:pointer;transition:all .3s}.ant-form-item-tooltip:hover{color:#202d40}.ant-form-item-control{display:flex;flex-direction:column;flex-grow:1}.ant-form-item-control:first-child:not([class^="ant-col-"]):not([class*=" ant-col-"]){width:100%}.ant-form-item-control-input{position:relative;display:flex;align-items:center;min-height:32px}.ant-form-item-control-input-content{flex:auto;max-width:100%}.ant-form-item-explain,.ant-form-item-extra{clear:both;margin-top:4px;color:#000a2999;font-size:12px;line-height:1.5715;transition:color .3s cubic-bezier(.215,.61,.355,1)}.show-help-enter,.show-help-appear,.show-help-leave{animation-duration:.3s;animation-fill-mode:both;animation-play-state:paused}.show-help-enter.show-help-enter-active,.show-help-appear.show-help-appear-active{animation-name:antShowHelpIn;animation-play-state:running}.show-help-leave.show-help-leave-active{animation-name:antShowHelpOut;animation-play-state:running;pointer-events:none}.show-help-enter,.show-help-appear{opacity:0;animation-timing-function:cubic-bezier(.645,.045,.355,1)}.show-help-leave{animation-timing-function:cubic-bezier(.645,.045,.355,1)}@keyframes antShowHelpIn{0%{transform:translateY(-5px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes antShowHelpOut{to{transform:translateY(-5px);opacity:0}}@keyframes diffZoomIn1{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes diffZoomIn2{0%{transform:scale(0)}to{transform:scale(1)}}@keyframes diffZoomIn3{0%{transform:scale(0)}to{transform:scale(1)}}.ant-form-rtl{direction:rtl}.ant-form-rtl .ant-form-item-label{text-align:left}.ant-form-rtl .ant-form-item-label>label.ant-form-item-required:before{margin-right:0;margin-left:4px}.ant-form-rtl .ant-form-item-label>label:after{margin:0 2px 0 8px}.ant-col-rtl .ant-form-item-control:first-child{width:100%}.ant-form-rtl .ant-form-item-has-feedback .ant-input{padding-right:8px;padding-left:24px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input-suffix{padding-right:8px;padding-left:18px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-affix-wrapper .ant-input{padding:0}.ant-form-rtl .ant-form-item-has-feedback .ant-input-search:not(.ant-input-search-enter-button) .ant-input-suffix{right:auto;left:28px}.ant-form-rtl .ant-form-item-has-feedback .ant-input-number{padding-left:18px}.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-arrow,.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-selection__clear,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-arrow,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection__clear{right:auto;left:28px}.ant-form-rtl .ant-form-item-has-feedback>.ant-select .ant-select-selection-selected-value,.ant-form-rtl .ant-form-item-has-feedback :not(.ant-input-group-addon)>.ant-select .ant-select-selection-selected-value{padding-right:0;padding-left:42px}.ant-form-rtl .ant-form-item-has-feedback .ant-cascader-picker-arrow{margin-right:0;margin-left:17px}.ant-form-rtl .ant-form-item-has-feedback .ant-cascader-picker-clear{right:auto;left:28px}.ant-form-rtl .ant-form-item-has-feedback .ant-picker,.ant-form-rtl .ant-form-item-has-feedback .ant-picker-large,.ant-form-rtl .ant-form-item-has-feedback .ant-picker-small{padding-right:8px;padding-left:26.2px}.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-success .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-warning .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-has-error .ant-form-item-children-icon,.ant-form-rtl .ant-form-item-has-feedback.ant-form-item-is-validating .ant-form-item-children-icon{right:auto;left:0}.ant-form-rtl.ant-form-inline .ant-form-item{margin-right:0;margin-left:16px}.ant-row{display:flex;flex-flow:row wrap}.ant-row:before,.ant-row:after{display:flex}.ant-row-start{justify-content:flex-start}.ant-row-center{justify-content:center}.ant-row-end{justify-content:flex-end}.ant-row-space-between{justify-content:space-between}.ant-row-space-around{justify-content:space-around}.ant-row-top{align-items:flex-start}.ant-row-middle{align-items:center}.ant-row-bottom{align-items:flex-end}.ant-col{position:relative;max-width:100%;min-height:1px}.ant-col-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-push-24{left:100%}.ant-col-pull-24{right:100%}.ant-col-offset-24{margin-left:100%}.ant-col-order-24{order:24}.ant-col-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-push-23{left:95.83333333%}.ant-col-pull-23{right:95.83333333%}.ant-col-offset-23{margin-left:95.83333333%}.ant-col-order-23{order:23}.ant-col-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-push-22{left:91.66666667%}.ant-col-pull-22{right:91.66666667%}.ant-col-offset-22{margin-left:91.66666667%}.ant-col-order-22{order:22}.ant-col-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-push-21{left:87.5%}.ant-col-pull-21{right:87.5%}.ant-col-offset-21{margin-left:87.5%}.ant-col-order-21{order:21}.ant-col-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-push-20{left:83.33333333%}.ant-col-pull-20{right:83.33333333%}.ant-col-offset-20{margin-left:83.33333333%}.ant-col-order-20{order:20}.ant-col-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-push-19{left:79.16666667%}.ant-col-pull-19{right:79.16666667%}.ant-col-offset-19{margin-left:79.16666667%}.ant-col-order-19{order:19}.ant-col-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-push-18{left:75%}.ant-col-pull-18{right:75%}.ant-col-offset-18{margin-left:75%}.ant-col-order-18{order:18}.ant-col-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-push-17{left:70.83333333%}.ant-col-pull-17{right:70.83333333%}.ant-col-offset-17{margin-left:70.83333333%}.ant-col-order-17{order:17}.ant-col-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-push-16{left:66.66666667%}.ant-col-pull-16{right:66.66666667%}.ant-col-offset-16{margin-left:66.66666667%}.ant-col-order-16{order:16}.ant-col-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-push-15{left:62.5%}.ant-col-pull-15{right:62.5%}.ant-col-offset-15{margin-left:62.5%}.ant-col-order-15{order:15}.ant-col-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-push-14{left:58.33333333%}.ant-col-pull-14{right:58.33333333%}.ant-col-offset-14{margin-left:58.33333333%}.ant-col-order-14{order:14}.ant-col-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-push-13{left:54.16666667%}.ant-col-pull-13{right:54.16666667%}.ant-col-offset-13{margin-left:54.16666667%}.ant-col-order-13{order:13}.ant-col-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-push-12{left:50%}.ant-col-pull-12{right:50%}.ant-col-offset-12{margin-left:50%}.ant-col-order-12{order:12}.ant-col-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-push-11{left:45.83333333%}.ant-col-pull-11{right:45.83333333%}.ant-col-offset-11{margin-left:45.83333333%}.ant-col-order-11{order:11}.ant-col-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-push-10{left:41.66666667%}.ant-col-pull-10{right:41.66666667%}.ant-col-offset-10{margin-left:41.66666667%}.ant-col-order-10{order:10}.ant-col-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-push-9{left:37.5%}.ant-col-pull-9{right:37.5%}.ant-col-offset-9{margin-left:37.5%}.ant-col-order-9{order:9}.ant-col-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-push-8{left:33.33333333%}.ant-col-pull-8{right:33.33333333%}.ant-col-offset-8{margin-left:33.33333333%}.ant-col-order-8{order:8}.ant-col-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-push-7{left:29.16666667%}.ant-col-pull-7{right:29.16666667%}.ant-col-offset-7{margin-left:29.16666667%}.ant-col-order-7{order:7}.ant-col-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-push-6{left:25%}.ant-col-pull-6{right:25%}.ant-col-offset-6{margin-left:25%}.ant-col-order-6{order:6}.ant-col-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-push-5{left:20.83333333%}.ant-col-pull-5{right:20.83333333%}.ant-col-offset-5{margin-left:20.83333333%}.ant-col-order-5{order:5}.ant-col-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-push-4{left:16.66666667%}.ant-col-pull-4{right:16.66666667%}.ant-col-offset-4{margin-left:16.66666667%}.ant-col-order-4{order:4}.ant-col-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-push-3{left:12.5%}.ant-col-pull-3{right:12.5%}.ant-col-offset-3{margin-left:12.5%}.ant-col-order-3{order:3}.ant-col-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-push-2{left:8.33333333%}.ant-col-pull-2{right:8.33333333%}.ant-col-offset-2{margin-left:8.33333333%}.ant-col-order-2{order:2}.ant-col-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-push-1{left:4.16666667%}.ant-col-pull-1{right:4.16666667%}.ant-col-offset-1{margin-left:4.16666667%}.ant-col-order-1{order:1}.ant-col-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-offset-0{margin-left:0}.ant-col-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-offset-0.ant-col-rtl{margin-right:0}.ant-col-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}.ant-col-xs-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xs-push-24{left:100%}.ant-col-xs-pull-24{right:100%}.ant-col-xs-offset-24{margin-left:100%}.ant-col-xs-order-24{order:24}.ant-col-xs-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xs-push-23{left:95.83333333%}.ant-col-xs-pull-23{right:95.83333333%}.ant-col-xs-offset-23{margin-left:95.83333333%}.ant-col-xs-order-23{order:23}.ant-col-xs-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xs-push-22{left:91.66666667%}.ant-col-xs-pull-22{right:91.66666667%}.ant-col-xs-offset-22{margin-left:91.66666667%}.ant-col-xs-order-22{order:22}.ant-col-xs-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xs-push-21{left:87.5%}.ant-col-xs-pull-21{right:87.5%}.ant-col-xs-offset-21{margin-left:87.5%}.ant-col-xs-order-21{order:21}.ant-col-xs-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xs-push-20{left:83.33333333%}.ant-col-xs-pull-20{right:83.33333333%}.ant-col-xs-offset-20{margin-left:83.33333333%}.ant-col-xs-order-20{order:20}.ant-col-xs-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xs-push-19{left:79.16666667%}.ant-col-xs-pull-19{right:79.16666667%}.ant-col-xs-offset-19{margin-left:79.16666667%}.ant-col-xs-order-19{order:19}.ant-col-xs-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xs-push-18{left:75%}.ant-col-xs-pull-18{right:75%}.ant-col-xs-offset-18{margin-left:75%}.ant-col-xs-order-18{order:18}.ant-col-xs-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xs-push-17{left:70.83333333%}.ant-col-xs-pull-17{right:70.83333333%}.ant-col-xs-offset-17{margin-left:70.83333333%}.ant-col-xs-order-17{order:17}.ant-col-xs-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xs-push-16{left:66.66666667%}.ant-col-xs-pull-16{right:66.66666667%}.ant-col-xs-offset-16{margin-left:66.66666667%}.ant-col-xs-order-16{order:16}.ant-col-xs-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xs-push-15{left:62.5%}.ant-col-xs-pull-15{right:62.5%}.ant-col-xs-offset-15{margin-left:62.5%}.ant-col-xs-order-15{order:15}.ant-col-xs-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xs-push-14{left:58.33333333%}.ant-col-xs-pull-14{right:58.33333333%}.ant-col-xs-offset-14{margin-left:58.33333333%}.ant-col-xs-order-14{order:14}.ant-col-xs-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xs-push-13{left:54.16666667%}.ant-col-xs-pull-13{right:54.16666667%}.ant-col-xs-offset-13{margin-left:54.16666667%}.ant-col-xs-order-13{order:13}.ant-col-xs-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xs-push-12{left:50%}.ant-col-xs-pull-12{right:50%}.ant-col-xs-offset-12{margin-left:50%}.ant-col-xs-order-12{order:12}.ant-col-xs-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xs-push-11{left:45.83333333%}.ant-col-xs-pull-11{right:45.83333333%}.ant-col-xs-offset-11{margin-left:45.83333333%}.ant-col-xs-order-11{order:11}.ant-col-xs-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xs-push-10{left:41.66666667%}.ant-col-xs-pull-10{right:41.66666667%}.ant-col-xs-offset-10{margin-left:41.66666667%}.ant-col-xs-order-10{order:10}.ant-col-xs-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xs-push-9{left:37.5%}.ant-col-xs-pull-9{right:37.5%}.ant-col-xs-offset-9{margin-left:37.5%}.ant-col-xs-order-9{order:9}.ant-col-xs-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xs-push-8{left:33.33333333%}.ant-col-xs-pull-8{right:33.33333333%}.ant-col-xs-offset-8{margin-left:33.33333333%}.ant-col-xs-order-8{order:8}.ant-col-xs-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xs-push-7{left:29.16666667%}.ant-col-xs-pull-7{right:29.16666667%}.ant-col-xs-offset-7{margin-left:29.16666667%}.ant-col-xs-order-7{order:7}.ant-col-xs-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xs-push-6{left:25%}.ant-col-xs-pull-6{right:25%}.ant-col-xs-offset-6{margin-left:25%}.ant-col-xs-order-6{order:6}.ant-col-xs-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xs-push-5{left:20.83333333%}.ant-col-xs-pull-5{right:20.83333333%}.ant-col-xs-offset-5{margin-left:20.83333333%}.ant-col-xs-order-5{order:5}.ant-col-xs-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xs-push-4{left:16.66666667%}.ant-col-xs-pull-4{right:16.66666667%}.ant-col-xs-offset-4{margin-left:16.66666667%}.ant-col-xs-order-4{order:4}.ant-col-xs-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xs-push-3{left:12.5%}.ant-col-xs-pull-3{right:12.5%}.ant-col-xs-offset-3{margin-left:12.5%}.ant-col-xs-order-3{order:3}.ant-col-xs-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xs-push-2{left:8.33333333%}.ant-col-xs-pull-2{right:8.33333333%}.ant-col-xs-offset-2{margin-left:8.33333333%}.ant-col-xs-order-2{order:2}.ant-col-xs-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xs-push-1{left:4.16666667%}.ant-col-xs-pull-1{right:4.16666667%}.ant-col-xs-offset-1{margin-left:4.16666667%}.ant-col-xs-order-1{order:1}.ant-col-xs-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xs-push-0{left:auto}.ant-col-xs-pull-0{right:auto}.ant-col-xs-offset-0{margin-left:0}.ant-col-xs-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xs-push-0.ant-col-rtl{right:auto}.ant-col-xs-pull-0.ant-col-rtl{left:auto}.ant-col-xs-offset-0.ant-col-rtl{margin-right:0}.ant-col-xs-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xs-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xs-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xs-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xs-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xs-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xs-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xs-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xs-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xs-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xs-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xs-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xs-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xs-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xs-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xs-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xs-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xs-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xs-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xs-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xs-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xs-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xs-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xs-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xs-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xs-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xs-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xs-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xs-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xs-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xs-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xs-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xs-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xs-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xs-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xs-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xs-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xs-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xs-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xs-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xs-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xs-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xs-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xs-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xs-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xs-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xs-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xs-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xs-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xs-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xs-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xs-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xs-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xs-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xs-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xs-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xs-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xs-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xs-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xs-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xs-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xs-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xs-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xs-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xs-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xs-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xs-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xs-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xs-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xs-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xs-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xs-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}@media (min-width: 576px){.ant-col-sm-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-sm-push-24{left:100%}.ant-col-sm-pull-24{right:100%}.ant-col-sm-offset-24{margin-left:100%}.ant-col-sm-order-24{order:24}.ant-col-sm-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-sm-push-23{left:95.83333333%}.ant-col-sm-pull-23{right:95.83333333%}.ant-col-sm-offset-23{margin-left:95.83333333%}.ant-col-sm-order-23{order:23}.ant-col-sm-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-sm-push-22{left:91.66666667%}.ant-col-sm-pull-22{right:91.66666667%}.ant-col-sm-offset-22{margin-left:91.66666667%}.ant-col-sm-order-22{order:22}.ant-col-sm-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-sm-push-21{left:87.5%}.ant-col-sm-pull-21{right:87.5%}.ant-col-sm-offset-21{margin-left:87.5%}.ant-col-sm-order-21{order:21}.ant-col-sm-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-sm-push-20{left:83.33333333%}.ant-col-sm-pull-20{right:83.33333333%}.ant-col-sm-offset-20{margin-left:83.33333333%}.ant-col-sm-order-20{order:20}.ant-col-sm-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-sm-push-19{left:79.16666667%}.ant-col-sm-pull-19{right:79.16666667%}.ant-col-sm-offset-19{margin-left:79.16666667%}.ant-col-sm-order-19{order:19}.ant-col-sm-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-sm-push-18{left:75%}.ant-col-sm-pull-18{right:75%}.ant-col-sm-offset-18{margin-left:75%}.ant-col-sm-order-18{order:18}.ant-col-sm-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-sm-push-17{left:70.83333333%}.ant-col-sm-pull-17{right:70.83333333%}.ant-col-sm-offset-17{margin-left:70.83333333%}.ant-col-sm-order-17{order:17}.ant-col-sm-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-sm-push-16{left:66.66666667%}.ant-col-sm-pull-16{right:66.66666667%}.ant-col-sm-offset-16{margin-left:66.66666667%}.ant-col-sm-order-16{order:16}.ant-col-sm-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-sm-push-15{left:62.5%}.ant-col-sm-pull-15{right:62.5%}.ant-col-sm-offset-15{margin-left:62.5%}.ant-col-sm-order-15{order:15}.ant-col-sm-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-sm-push-14{left:58.33333333%}.ant-col-sm-pull-14{right:58.33333333%}.ant-col-sm-offset-14{margin-left:58.33333333%}.ant-col-sm-order-14{order:14}.ant-col-sm-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-sm-push-13{left:54.16666667%}.ant-col-sm-pull-13{right:54.16666667%}.ant-col-sm-offset-13{margin-left:54.16666667%}.ant-col-sm-order-13{order:13}.ant-col-sm-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-sm-push-12{left:50%}.ant-col-sm-pull-12{right:50%}.ant-col-sm-offset-12{margin-left:50%}.ant-col-sm-order-12{order:12}.ant-col-sm-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-sm-push-11{left:45.83333333%}.ant-col-sm-pull-11{right:45.83333333%}.ant-col-sm-offset-11{margin-left:45.83333333%}.ant-col-sm-order-11{order:11}.ant-col-sm-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-sm-push-10{left:41.66666667%}.ant-col-sm-pull-10{right:41.66666667%}.ant-col-sm-offset-10{margin-left:41.66666667%}.ant-col-sm-order-10{order:10}.ant-col-sm-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-sm-push-9{left:37.5%}.ant-col-sm-pull-9{right:37.5%}.ant-col-sm-offset-9{margin-left:37.5%}.ant-col-sm-order-9{order:9}.ant-col-sm-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-sm-push-8{left:33.33333333%}.ant-col-sm-pull-8{right:33.33333333%}.ant-col-sm-offset-8{margin-left:33.33333333%}.ant-col-sm-order-8{order:8}.ant-col-sm-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-sm-push-7{left:29.16666667%}.ant-col-sm-pull-7{right:29.16666667%}.ant-col-sm-offset-7{margin-left:29.16666667%}.ant-col-sm-order-7{order:7}.ant-col-sm-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-sm-push-6{left:25%}.ant-col-sm-pull-6{right:25%}.ant-col-sm-offset-6{margin-left:25%}.ant-col-sm-order-6{order:6}.ant-col-sm-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-sm-push-5{left:20.83333333%}.ant-col-sm-pull-5{right:20.83333333%}.ant-col-sm-offset-5{margin-left:20.83333333%}.ant-col-sm-order-5{order:5}.ant-col-sm-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-sm-push-4{left:16.66666667%}.ant-col-sm-pull-4{right:16.66666667%}.ant-col-sm-offset-4{margin-left:16.66666667%}.ant-col-sm-order-4{order:4}.ant-col-sm-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-sm-push-3{left:12.5%}.ant-col-sm-pull-3{right:12.5%}.ant-col-sm-offset-3{margin-left:12.5%}.ant-col-sm-order-3{order:3}.ant-col-sm-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-sm-push-2{left:8.33333333%}.ant-col-sm-pull-2{right:8.33333333%}.ant-col-sm-offset-2{margin-left:8.33333333%}.ant-col-sm-order-2{order:2}.ant-col-sm-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-sm-push-1{left:4.16666667%}.ant-col-sm-pull-1{right:4.16666667%}.ant-col-sm-offset-1{margin-left:4.16666667%}.ant-col-sm-order-1{order:1}.ant-col-sm-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-sm-push-0{left:auto}.ant-col-sm-pull-0{right:auto}.ant-col-sm-offset-0{margin-left:0}.ant-col-sm-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-sm-push-0.ant-col-rtl{right:auto}.ant-col-sm-pull-0.ant-col-rtl{left:auto}.ant-col-sm-offset-0.ant-col-rtl{margin-right:0}.ant-col-sm-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-sm-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-sm-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-sm-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-sm-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-sm-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-sm-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-sm-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-sm-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-sm-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-sm-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-sm-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-sm-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-sm-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-sm-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-sm-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-sm-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-sm-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-sm-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-sm-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-sm-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-sm-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-sm-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-sm-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-sm-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-sm-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-sm-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-sm-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-sm-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-sm-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-sm-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-sm-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-sm-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-sm-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-sm-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-sm-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-sm-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-sm-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-sm-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-sm-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-sm-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-sm-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-sm-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-sm-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-sm-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-sm-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-sm-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-sm-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-sm-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-sm-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-sm-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-sm-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-sm-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-sm-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-sm-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-sm-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-sm-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-sm-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-sm-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-sm-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-sm-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-sm-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-sm-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-sm-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-sm-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-sm-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-sm-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-sm-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-sm-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-sm-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-sm-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-sm-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 768px){.ant-col-md-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-md-push-24{left:100%}.ant-col-md-pull-24{right:100%}.ant-col-md-offset-24{margin-left:100%}.ant-col-md-order-24{order:24}.ant-col-md-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-md-push-23{left:95.83333333%}.ant-col-md-pull-23{right:95.83333333%}.ant-col-md-offset-23{margin-left:95.83333333%}.ant-col-md-order-23{order:23}.ant-col-md-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-md-push-22{left:91.66666667%}.ant-col-md-pull-22{right:91.66666667%}.ant-col-md-offset-22{margin-left:91.66666667%}.ant-col-md-order-22{order:22}.ant-col-md-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-md-push-21{left:87.5%}.ant-col-md-pull-21{right:87.5%}.ant-col-md-offset-21{margin-left:87.5%}.ant-col-md-order-21{order:21}.ant-col-md-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-md-push-20{left:83.33333333%}.ant-col-md-pull-20{right:83.33333333%}.ant-col-md-offset-20{margin-left:83.33333333%}.ant-col-md-order-20{order:20}.ant-col-md-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-md-push-19{left:79.16666667%}.ant-col-md-pull-19{right:79.16666667%}.ant-col-md-offset-19{margin-left:79.16666667%}.ant-col-md-order-19{order:19}.ant-col-md-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-md-push-18{left:75%}.ant-col-md-pull-18{right:75%}.ant-col-md-offset-18{margin-left:75%}.ant-col-md-order-18{order:18}.ant-col-md-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-md-push-17{left:70.83333333%}.ant-col-md-pull-17{right:70.83333333%}.ant-col-md-offset-17{margin-left:70.83333333%}.ant-col-md-order-17{order:17}.ant-col-md-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-md-push-16{left:66.66666667%}.ant-col-md-pull-16{right:66.66666667%}.ant-col-md-offset-16{margin-left:66.66666667%}.ant-col-md-order-16{order:16}.ant-col-md-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-md-push-15{left:62.5%}.ant-col-md-pull-15{right:62.5%}.ant-col-md-offset-15{margin-left:62.5%}.ant-col-md-order-15{order:15}.ant-col-md-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-md-push-14{left:58.33333333%}.ant-col-md-pull-14{right:58.33333333%}.ant-col-md-offset-14{margin-left:58.33333333%}.ant-col-md-order-14{order:14}.ant-col-md-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-md-push-13{left:54.16666667%}.ant-col-md-pull-13{right:54.16666667%}.ant-col-md-offset-13{margin-left:54.16666667%}.ant-col-md-order-13{order:13}.ant-col-md-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-md-push-12{left:50%}.ant-col-md-pull-12{right:50%}.ant-col-md-offset-12{margin-left:50%}.ant-col-md-order-12{order:12}.ant-col-md-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-md-push-11{left:45.83333333%}.ant-col-md-pull-11{right:45.83333333%}.ant-col-md-offset-11{margin-left:45.83333333%}.ant-col-md-order-11{order:11}.ant-col-md-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-md-push-10{left:41.66666667%}.ant-col-md-pull-10{right:41.66666667%}.ant-col-md-offset-10{margin-left:41.66666667%}.ant-col-md-order-10{order:10}.ant-col-md-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-md-push-9{left:37.5%}.ant-col-md-pull-9{right:37.5%}.ant-col-md-offset-9{margin-left:37.5%}.ant-col-md-order-9{order:9}.ant-col-md-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-md-push-8{left:33.33333333%}.ant-col-md-pull-8{right:33.33333333%}.ant-col-md-offset-8{margin-left:33.33333333%}.ant-col-md-order-8{order:8}.ant-col-md-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-md-push-7{left:29.16666667%}.ant-col-md-pull-7{right:29.16666667%}.ant-col-md-offset-7{margin-left:29.16666667%}.ant-col-md-order-7{order:7}.ant-col-md-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-md-push-6{left:25%}.ant-col-md-pull-6{right:25%}.ant-col-md-offset-6{margin-left:25%}.ant-col-md-order-6{order:6}.ant-col-md-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-md-push-5{left:20.83333333%}.ant-col-md-pull-5{right:20.83333333%}.ant-col-md-offset-5{margin-left:20.83333333%}.ant-col-md-order-5{order:5}.ant-col-md-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-md-push-4{left:16.66666667%}.ant-col-md-pull-4{right:16.66666667%}.ant-col-md-offset-4{margin-left:16.66666667%}.ant-col-md-order-4{order:4}.ant-col-md-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-md-push-3{left:12.5%}.ant-col-md-pull-3{right:12.5%}.ant-col-md-offset-3{margin-left:12.5%}.ant-col-md-order-3{order:3}.ant-col-md-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-md-push-2{left:8.33333333%}.ant-col-md-pull-2{right:8.33333333%}.ant-col-md-offset-2{margin-left:8.33333333%}.ant-col-md-order-2{order:2}.ant-col-md-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-md-push-1{left:4.16666667%}.ant-col-md-pull-1{right:4.16666667%}.ant-col-md-offset-1{margin-left:4.16666667%}.ant-col-md-order-1{order:1}.ant-col-md-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-md-push-0{left:auto}.ant-col-md-pull-0{right:auto}.ant-col-md-offset-0{margin-left:0}.ant-col-md-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-md-push-0.ant-col-rtl{right:auto}.ant-col-md-pull-0.ant-col-rtl{left:auto}.ant-col-md-offset-0.ant-col-rtl{margin-right:0}.ant-col-md-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-md-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-md-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-md-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-md-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-md-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-md-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-md-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-md-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-md-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-md-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-md-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-md-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-md-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-md-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-md-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-md-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-md-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-md-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-md-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-md-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-md-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-md-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-md-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-md-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-md-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-md-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-md-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-md-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-md-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-md-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-md-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-md-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-md-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-md-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-md-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-md-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-md-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-md-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-md-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-md-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-md-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-md-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-md-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-md-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-md-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-md-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-md-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-md-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-md-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-md-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-md-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-md-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-md-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-md-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-md-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-md-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-md-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-md-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-md-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-md-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-md-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-md-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-md-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-md-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-md-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-md-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-md-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-md-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-md-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-md-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-md-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 992px){.ant-col-lg-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-lg-push-24{left:100%}.ant-col-lg-pull-24{right:100%}.ant-col-lg-offset-24{margin-left:100%}.ant-col-lg-order-24{order:24}.ant-col-lg-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-lg-push-23{left:95.83333333%}.ant-col-lg-pull-23{right:95.83333333%}.ant-col-lg-offset-23{margin-left:95.83333333%}.ant-col-lg-order-23{order:23}.ant-col-lg-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-lg-push-22{left:91.66666667%}.ant-col-lg-pull-22{right:91.66666667%}.ant-col-lg-offset-22{margin-left:91.66666667%}.ant-col-lg-order-22{order:22}.ant-col-lg-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-lg-push-21{left:87.5%}.ant-col-lg-pull-21{right:87.5%}.ant-col-lg-offset-21{margin-left:87.5%}.ant-col-lg-order-21{order:21}.ant-col-lg-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-lg-push-20{left:83.33333333%}.ant-col-lg-pull-20{right:83.33333333%}.ant-col-lg-offset-20{margin-left:83.33333333%}.ant-col-lg-order-20{order:20}.ant-col-lg-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-lg-push-19{left:79.16666667%}.ant-col-lg-pull-19{right:79.16666667%}.ant-col-lg-offset-19{margin-left:79.16666667%}.ant-col-lg-order-19{order:19}.ant-col-lg-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-lg-push-18{left:75%}.ant-col-lg-pull-18{right:75%}.ant-col-lg-offset-18{margin-left:75%}.ant-col-lg-order-18{order:18}.ant-col-lg-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-lg-push-17{left:70.83333333%}.ant-col-lg-pull-17{right:70.83333333%}.ant-col-lg-offset-17{margin-left:70.83333333%}.ant-col-lg-order-17{order:17}.ant-col-lg-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-lg-push-16{left:66.66666667%}.ant-col-lg-pull-16{right:66.66666667%}.ant-col-lg-offset-16{margin-left:66.66666667%}.ant-col-lg-order-16{order:16}.ant-col-lg-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-lg-push-15{left:62.5%}.ant-col-lg-pull-15{right:62.5%}.ant-col-lg-offset-15{margin-left:62.5%}.ant-col-lg-order-15{order:15}.ant-col-lg-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-lg-push-14{left:58.33333333%}.ant-col-lg-pull-14{right:58.33333333%}.ant-col-lg-offset-14{margin-left:58.33333333%}.ant-col-lg-order-14{order:14}.ant-col-lg-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-lg-push-13{left:54.16666667%}.ant-col-lg-pull-13{right:54.16666667%}.ant-col-lg-offset-13{margin-left:54.16666667%}.ant-col-lg-order-13{order:13}.ant-col-lg-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-lg-push-12{left:50%}.ant-col-lg-pull-12{right:50%}.ant-col-lg-offset-12{margin-left:50%}.ant-col-lg-order-12{order:12}.ant-col-lg-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-lg-push-11{left:45.83333333%}.ant-col-lg-pull-11{right:45.83333333%}.ant-col-lg-offset-11{margin-left:45.83333333%}.ant-col-lg-order-11{order:11}.ant-col-lg-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-lg-push-10{left:41.66666667%}.ant-col-lg-pull-10{right:41.66666667%}.ant-col-lg-offset-10{margin-left:41.66666667%}.ant-col-lg-order-10{order:10}.ant-col-lg-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-lg-push-9{left:37.5%}.ant-col-lg-pull-9{right:37.5%}.ant-col-lg-offset-9{margin-left:37.5%}.ant-col-lg-order-9{order:9}.ant-col-lg-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-lg-push-8{left:33.33333333%}.ant-col-lg-pull-8{right:33.33333333%}.ant-col-lg-offset-8{margin-left:33.33333333%}.ant-col-lg-order-8{order:8}.ant-col-lg-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-lg-push-7{left:29.16666667%}.ant-col-lg-pull-7{right:29.16666667%}.ant-col-lg-offset-7{margin-left:29.16666667%}.ant-col-lg-order-7{order:7}.ant-col-lg-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-lg-push-6{left:25%}.ant-col-lg-pull-6{right:25%}.ant-col-lg-offset-6{margin-left:25%}.ant-col-lg-order-6{order:6}.ant-col-lg-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-lg-push-5{left:20.83333333%}.ant-col-lg-pull-5{right:20.83333333%}.ant-col-lg-offset-5{margin-left:20.83333333%}.ant-col-lg-order-5{order:5}.ant-col-lg-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-lg-push-4{left:16.66666667%}.ant-col-lg-pull-4{right:16.66666667%}.ant-col-lg-offset-4{margin-left:16.66666667%}.ant-col-lg-order-4{order:4}.ant-col-lg-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-lg-push-3{left:12.5%}.ant-col-lg-pull-3{right:12.5%}.ant-col-lg-offset-3{margin-left:12.5%}.ant-col-lg-order-3{order:3}.ant-col-lg-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-lg-push-2{left:8.33333333%}.ant-col-lg-pull-2{right:8.33333333%}.ant-col-lg-offset-2{margin-left:8.33333333%}.ant-col-lg-order-2{order:2}.ant-col-lg-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-lg-push-1{left:4.16666667%}.ant-col-lg-pull-1{right:4.16666667%}.ant-col-lg-offset-1{margin-left:4.16666667%}.ant-col-lg-order-1{order:1}.ant-col-lg-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-lg-push-0{left:auto}.ant-col-lg-pull-0{right:auto}.ant-col-lg-offset-0{margin-left:0}.ant-col-lg-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-lg-push-0.ant-col-rtl{right:auto}.ant-col-lg-pull-0.ant-col-rtl{left:auto}.ant-col-lg-offset-0.ant-col-rtl{margin-right:0}.ant-col-lg-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-lg-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-lg-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-lg-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-lg-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-lg-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-lg-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-lg-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-lg-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-lg-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-lg-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-lg-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-lg-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-lg-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-lg-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-lg-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-lg-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-lg-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-lg-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-lg-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-lg-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-lg-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-lg-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-lg-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-lg-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-lg-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-lg-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-lg-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-lg-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-lg-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-lg-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-lg-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-lg-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-lg-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-lg-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-lg-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-lg-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-lg-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-lg-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-lg-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-lg-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-lg-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-lg-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-lg-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-lg-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-lg-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-lg-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-lg-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-lg-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-lg-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-lg-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-lg-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-lg-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-lg-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-lg-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-lg-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-lg-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-lg-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-lg-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-lg-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-lg-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-lg-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-lg-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-lg-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-lg-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-lg-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-lg-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-lg-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-lg-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-lg-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-lg-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-lg-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 1200px){.ant-col-xl-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xl-push-24{left:100%}.ant-col-xl-pull-24{right:100%}.ant-col-xl-offset-24{margin-left:100%}.ant-col-xl-order-24{order:24}.ant-col-xl-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xl-push-23{left:95.83333333%}.ant-col-xl-pull-23{right:95.83333333%}.ant-col-xl-offset-23{margin-left:95.83333333%}.ant-col-xl-order-23{order:23}.ant-col-xl-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xl-push-22{left:91.66666667%}.ant-col-xl-pull-22{right:91.66666667%}.ant-col-xl-offset-22{margin-left:91.66666667%}.ant-col-xl-order-22{order:22}.ant-col-xl-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xl-push-21{left:87.5%}.ant-col-xl-pull-21{right:87.5%}.ant-col-xl-offset-21{margin-left:87.5%}.ant-col-xl-order-21{order:21}.ant-col-xl-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xl-push-20{left:83.33333333%}.ant-col-xl-pull-20{right:83.33333333%}.ant-col-xl-offset-20{margin-left:83.33333333%}.ant-col-xl-order-20{order:20}.ant-col-xl-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xl-push-19{left:79.16666667%}.ant-col-xl-pull-19{right:79.16666667%}.ant-col-xl-offset-19{margin-left:79.16666667%}.ant-col-xl-order-19{order:19}.ant-col-xl-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xl-push-18{left:75%}.ant-col-xl-pull-18{right:75%}.ant-col-xl-offset-18{margin-left:75%}.ant-col-xl-order-18{order:18}.ant-col-xl-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xl-push-17{left:70.83333333%}.ant-col-xl-pull-17{right:70.83333333%}.ant-col-xl-offset-17{margin-left:70.83333333%}.ant-col-xl-order-17{order:17}.ant-col-xl-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xl-push-16{left:66.66666667%}.ant-col-xl-pull-16{right:66.66666667%}.ant-col-xl-offset-16{margin-left:66.66666667%}.ant-col-xl-order-16{order:16}.ant-col-xl-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xl-push-15{left:62.5%}.ant-col-xl-pull-15{right:62.5%}.ant-col-xl-offset-15{margin-left:62.5%}.ant-col-xl-order-15{order:15}.ant-col-xl-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xl-push-14{left:58.33333333%}.ant-col-xl-pull-14{right:58.33333333%}.ant-col-xl-offset-14{margin-left:58.33333333%}.ant-col-xl-order-14{order:14}.ant-col-xl-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xl-push-13{left:54.16666667%}.ant-col-xl-pull-13{right:54.16666667%}.ant-col-xl-offset-13{margin-left:54.16666667%}.ant-col-xl-order-13{order:13}.ant-col-xl-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xl-push-12{left:50%}.ant-col-xl-pull-12{right:50%}.ant-col-xl-offset-12{margin-left:50%}.ant-col-xl-order-12{order:12}.ant-col-xl-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xl-push-11{left:45.83333333%}.ant-col-xl-pull-11{right:45.83333333%}.ant-col-xl-offset-11{margin-left:45.83333333%}.ant-col-xl-order-11{order:11}.ant-col-xl-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xl-push-10{left:41.66666667%}.ant-col-xl-pull-10{right:41.66666667%}.ant-col-xl-offset-10{margin-left:41.66666667%}.ant-col-xl-order-10{order:10}.ant-col-xl-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xl-push-9{left:37.5%}.ant-col-xl-pull-9{right:37.5%}.ant-col-xl-offset-9{margin-left:37.5%}.ant-col-xl-order-9{order:9}.ant-col-xl-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xl-push-8{left:33.33333333%}.ant-col-xl-pull-8{right:33.33333333%}.ant-col-xl-offset-8{margin-left:33.33333333%}.ant-col-xl-order-8{order:8}.ant-col-xl-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xl-push-7{left:29.16666667%}.ant-col-xl-pull-7{right:29.16666667%}.ant-col-xl-offset-7{margin-left:29.16666667%}.ant-col-xl-order-7{order:7}.ant-col-xl-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xl-push-6{left:25%}.ant-col-xl-pull-6{right:25%}.ant-col-xl-offset-6{margin-left:25%}.ant-col-xl-order-6{order:6}.ant-col-xl-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xl-push-5{left:20.83333333%}.ant-col-xl-pull-5{right:20.83333333%}.ant-col-xl-offset-5{margin-left:20.83333333%}.ant-col-xl-order-5{order:5}.ant-col-xl-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xl-push-4{left:16.66666667%}.ant-col-xl-pull-4{right:16.66666667%}.ant-col-xl-offset-4{margin-left:16.66666667%}.ant-col-xl-order-4{order:4}.ant-col-xl-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xl-push-3{left:12.5%}.ant-col-xl-pull-3{right:12.5%}.ant-col-xl-offset-3{margin-left:12.5%}.ant-col-xl-order-3{order:3}.ant-col-xl-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xl-push-2{left:8.33333333%}.ant-col-xl-pull-2{right:8.33333333%}.ant-col-xl-offset-2{margin-left:8.33333333%}.ant-col-xl-order-2{order:2}.ant-col-xl-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xl-push-1{left:4.16666667%}.ant-col-xl-pull-1{right:4.16666667%}.ant-col-xl-offset-1{margin-left:4.16666667%}.ant-col-xl-order-1{order:1}.ant-col-xl-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xl-push-0{left:auto}.ant-col-xl-pull-0{right:auto}.ant-col-xl-offset-0{margin-left:0}.ant-col-xl-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xl-push-0.ant-col-rtl{right:auto}.ant-col-xl-pull-0.ant-col-rtl{left:auto}.ant-col-xl-offset-0.ant-col-rtl{margin-right:0}.ant-col-xl-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xl-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xl-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xl-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xl-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xl-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xl-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xl-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xl-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xl-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xl-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xl-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xl-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xl-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xl-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xl-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xl-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xl-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xl-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xl-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xl-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xl-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xl-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xl-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xl-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xl-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xl-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xl-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xl-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xl-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xl-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xl-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xl-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xl-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xl-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xl-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xl-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xl-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xl-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xl-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xl-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xl-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xl-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xl-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xl-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xl-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xl-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xl-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xl-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xl-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xl-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xl-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xl-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xl-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xl-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xl-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xl-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xl-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xl-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xl-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xl-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xl-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xl-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xl-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xl-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xl-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xl-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xl-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xl-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xl-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xl-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xl-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}@media (min-width: 1600px){.ant-col-xxl-24{display:block;flex:0 0 100%;max-width:100%}.ant-col-xxl-push-24{left:100%}.ant-col-xxl-pull-24{right:100%}.ant-col-xxl-offset-24{margin-left:100%}.ant-col-xxl-order-24{order:24}.ant-col-xxl-23{display:block;flex:0 0 95.83333333%;max-width:95.83333333%}.ant-col-xxl-push-23{left:95.83333333%}.ant-col-xxl-pull-23{right:95.83333333%}.ant-col-xxl-offset-23{margin-left:95.83333333%}.ant-col-xxl-order-23{order:23}.ant-col-xxl-22{display:block;flex:0 0 91.66666667%;max-width:91.66666667%}.ant-col-xxl-push-22{left:91.66666667%}.ant-col-xxl-pull-22{right:91.66666667%}.ant-col-xxl-offset-22{margin-left:91.66666667%}.ant-col-xxl-order-22{order:22}.ant-col-xxl-21{display:block;flex:0 0 87.5%;max-width:87.5%}.ant-col-xxl-push-21{left:87.5%}.ant-col-xxl-pull-21{right:87.5%}.ant-col-xxl-offset-21{margin-left:87.5%}.ant-col-xxl-order-21{order:21}.ant-col-xxl-20{display:block;flex:0 0 83.33333333%;max-width:83.33333333%}.ant-col-xxl-push-20{left:83.33333333%}.ant-col-xxl-pull-20{right:83.33333333%}.ant-col-xxl-offset-20{margin-left:83.33333333%}.ant-col-xxl-order-20{order:20}.ant-col-xxl-19{display:block;flex:0 0 79.16666667%;max-width:79.16666667%}.ant-col-xxl-push-19{left:79.16666667%}.ant-col-xxl-pull-19{right:79.16666667%}.ant-col-xxl-offset-19{margin-left:79.16666667%}.ant-col-xxl-order-19{order:19}.ant-col-xxl-18{display:block;flex:0 0 75%;max-width:75%}.ant-col-xxl-push-18{left:75%}.ant-col-xxl-pull-18{right:75%}.ant-col-xxl-offset-18{margin-left:75%}.ant-col-xxl-order-18{order:18}.ant-col-xxl-17{display:block;flex:0 0 70.83333333%;max-width:70.83333333%}.ant-col-xxl-push-17{left:70.83333333%}.ant-col-xxl-pull-17{right:70.83333333%}.ant-col-xxl-offset-17{margin-left:70.83333333%}.ant-col-xxl-order-17{order:17}.ant-col-xxl-16{display:block;flex:0 0 66.66666667%;max-width:66.66666667%}.ant-col-xxl-push-16{left:66.66666667%}.ant-col-xxl-pull-16{right:66.66666667%}.ant-col-xxl-offset-16{margin-left:66.66666667%}.ant-col-xxl-order-16{order:16}.ant-col-xxl-15{display:block;flex:0 0 62.5%;max-width:62.5%}.ant-col-xxl-push-15{left:62.5%}.ant-col-xxl-pull-15{right:62.5%}.ant-col-xxl-offset-15{margin-left:62.5%}.ant-col-xxl-order-15{order:15}.ant-col-xxl-14{display:block;flex:0 0 58.33333333%;max-width:58.33333333%}.ant-col-xxl-push-14{left:58.33333333%}.ant-col-xxl-pull-14{right:58.33333333%}.ant-col-xxl-offset-14{margin-left:58.33333333%}.ant-col-xxl-order-14{order:14}.ant-col-xxl-13{display:block;flex:0 0 54.16666667%;max-width:54.16666667%}.ant-col-xxl-push-13{left:54.16666667%}.ant-col-xxl-pull-13{right:54.16666667%}.ant-col-xxl-offset-13{margin-left:54.16666667%}.ant-col-xxl-order-13{order:13}.ant-col-xxl-12{display:block;flex:0 0 50%;max-width:50%}.ant-col-xxl-push-12{left:50%}.ant-col-xxl-pull-12{right:50%}.ant-col-xxl-offset-12{margin-left:50%}.ant-col-xxl-order-12{order:12}.ant-col-xxl-11{display:block;flex:0 0 45.83333333%;max-width:45.83333333%}.ant-col-xxl-push-11{left:45.83333333%}.ant-col-xxl-pull-11{right:45.83333333%}.ant-col-xxl-offset-11{margin-left:45.83333333%}.ant-col-xxl-order-11{order:11}.ant-col-xxl-10{display:block;flex:0 0 41.66666667%;max-width:41.66666667%}.ant-col-xxl-push-10{left:41.66666667%}.ant-col-xxl-pull-10{right:41.66666667%}.ant-col-xxl-offset-10{margin-left:41.66666667%}.ant-col-xxl-order-10{order:10}.ant-col-xxl-9{display:block;flex:0 0 37.5%;max-width:37.5%}.ant-col-xxl-push-9{left:37.5%}.ant-col-xxl-pull-9{right:37.5%}.ant-col-xxl-offset-9{margin-left:37.5%}.ant-col-xxl-order-9{order:9}.ant-col-xxl-8{display:block;flex:0 0 33.33333333%;max-width:33.33333333%}.ant-col-xxl-push-8{left:33.33333333%}.ant-col-xxl-pull-8{right:33.33333333%}.ant-col-xxl-offset-8{margin-left:33.33333333%}.ant-col-xxl-order-8{order:8}.ant-col-xxl-7{display:block;flex:0 0 29.16666667%;max-width:29.16666667%}.ant-col-xxl-push-7{left:29.16666667%}.ant-col-xxl-pull-7{right:29.16666667%}.ant-col-xxl-offset-7{margin-left:29.16666667%}.ant-col-xxl-order-7{order:7}.ant-col-xxl-6{display:block;flex:0 0 25%;max-width:25%}.ant-col-xxl-push-6{left:25%}.ant-col-xxl-pull-6{right:25%}.ant-col-xxl-offset-6{margin-left:25%}.ant-col-xxl-order-6{order:6}.ant-col-xxl-5{display:block;flex:0 0 20.83333333%;max-width:20.83333333%}.ant-col-xxl-push-5{left:20.83333333%}.ant-col-xxl-pull-5{right:20.83333333%}.ant-col-xxl-offset-5{margin-left:20.83333333%}.ant-col-xxl-order-5{order:5}.ant-col-xxl-4{display:block;flex:0 0 16.66666667%;max-width:16.66666667%}.ant-col-xxl-push-4{left:16.66666667%}.ant-col-xxl-pull-4{right:16.66666667%}.ant-col-xxl-offset-4{margin-left:16.66666667%}.ant-col-xxl-order-4{order:4}.ant-col-xxl-3{display:block;flex:0 0 12.5%;max-width:12.5%}.ant-col-xxl-push-3{left:12.5%}.ant-col-xxl-pull-3{right:12.5%}.ant-col-xxl-offset-3{margin-left:12.5%}.ant-col-xxl-order-3{order:3}.ant-col-xxl-2{display:block;flex:0 0 8.33333333%;max-width:8.33333333%}.ant-col-xxl-push-2{left:8.33333333%}.ant-col-xxl-pull-2{right:8.33333333%}.ant-col-xxl-offset-2{margin-left:8.33333333%}.ant-col-xxl-order-2{order:2}.ant-col-xxl-1{display:block;flex:0 0 4.16666667%;max-width:4.16666667%}.ant-col-xxl-push-1{left:4.16666667%}.ant-col-xxl-pull-1{right:4.16666667%}.ant-col-xxl-offset-1{margin-left:4.16666667%}.ant-col-xxl-order-1{order:1}.ant-col-xxl-0{display:none}.ant-col-push-0{left:auto}.ant-col-pull-0{right:auto}.ant-col-xxl-push-0{left:auto}.ant-col-xxl-pull-0{right:auto}.ant-col-xxl-offset-0{margin-left:0}.ant-col-xxl-order-0{order:0}.ant-col-push-0.ant-col-rtl{right:auto}.ant-col-pull-0.ant-col-rtl{left:auto}.ant-col-xxl-push-0.ant-col-rtl{right:auto}.ant-col-xxl-pull-0.ant-col-rtl{left:auto}.ant-col-xxl-offset-0.ant-col-rtl{margin-right:0}.ant-col-xxl-push-1.ant-col-rtl{right:4.16666667%;left:auto}.ant-col-xxl-pull-1.ant-col-rtl{right:auto;left:4.16666667%}.ant-col-xxl-offset-1.ant-col-rtl{margin-right:4.16666667%;margin-left:0}.ant-col-xxl-push-2.ant-col-rtl{right:8.33333333%;left:auto}.ant-col-xxl-pull-2.ant-col-rtl{right:auto;left:8.33333333%}.ant-col-xxl-offset-2.ant-col-rtl{margin-right:8.33333333%;margin-left:0}.ant-col-xxl-push-3.ant-col-rtl{right:12.5%;left:auto}.ant-col-xxl-pull-3.ant-col-rtl{right:auto;left:12.5%}.ant-col-xxl-offset-3.ant-col-rtl{margin-right:12.5%;margin-left:0}.ant-col-xxl-push-4.ant-col-rtl{right:16.66666667%;left:auto}.ant-col-xxl-pull-4.ant-col-rtl{right:auto;left:16.66666667%}.ant-col-xxl-offset-4.ant-col-rtl{margin-right:16.66666667%;margin-left:0}.ant-col-xxl-push-5.ant-col-rtl{right:20.83333333%;left:auto}.ant-col-xxl-pull-5.ant-col-rtl{right:auto;left:20.83333333%}.ant-col-xxl-offset-5.ant-col-rtl{margin-right:20.83333333%;margin-left:0}.ant-col-xxl-push-6.ant-col-rtl{right:25%;left:auto}.ant-col-xxl-pull-6.ant-col-rtl{right:auto;left:25%}.ant-col-xxl-offset-6.ant-col-rtl{margin-right:25%;margin-left:0}.ant-col-xxl-push-7.ant-col-rtl{right:29.16666667%;left:auto}.ant-col-xxl-pull-7.ant-col-rtl{right:auto;left:29.16666667%}.ant-col-xxl-offset-7.ant-col-rtl{margin-right:29.16666667%;margin-left:0}.ant-col-xxl-push-8.ant-col-rtl{right:33.33333333%;left:auto}.ant-col-xxl-pull-8.ant-col-rtl{right:auto;left:33.33333333%}.ant-col-xxl-offset-8.ant-col-rtl{margin-right:33.33333333%;margin-left:0}.ant-col-xxl-push-9.ant-col-rtl{right:37.5%;left:auto}.ant-col-xxl-pull-9.ant-col-rtl{right:auto;left:37.5%}.ant-col-xxl-offset-9.ant-col-rtl{margin-right:37.5%;margin-left:0}.ant-col-xxl-push-10.ant-col-rtl{right:41.66666667%;left:auto}.ant-col-xxl-pull-10.ant-col-rtl{right:auto;left:41.66666667%}.ant-col-xxl-offset-10.ant-col-rtl{margin-right:41.66666667%;margin-left:0}.ant-col-xxl-push-11.ant-col-rtl{right:45.83333333%;left:auto}.ant-col-xxl-pull-11.ant-col-rtl{right:auto;left:45.83333333%}.ant-col-xxl-offset-11.ant-col-rtl{margin-right:45.83333333%;margin-left:0}.ant-col-xxl-push-12.ant-col-rtl{right:50%;left:auto}.ant-col-xxl-pull-12.ant-col-rtl{right:auto;left:50%}.ant-col-xxl-offset-12.ant-col-rtl{margin-right:50%;margin-left:0}.ant-col-xxl-push-13.ant-col-rtl{right:54.16666667%;left:auto}.ant-col-xxl-pull-13.ant-col-rtl{right:auto;left:54.16666667%}.ant-col-xxl-offset-13.ant-col-rtl{margin-right:54.16666667%;margin-left:0}.ant-col-xxl-push-14.ant-col-rtl{right:58.33333333%;left:auto}.ant-col-xxl-pull-14.ant-col-rtl{right:auto;left:58.33333333%}.ant-col-xxl-offset-14.ant-col-rtl{margin-right:58.33333333%;margin-left:0}.ant-col-xxl-push-15.ant-col-rtl{right:62.5%;left:auto}.ant-col-xxl-pull-15.ant-col-rtl{right:auto;left:62.5%}.ant-col-xxl-offset-15.ant-col-rtl{margin-right:62.5%;margin-left:0}.ant-col-xxl-push-16.ant-col-rtl{right:66.66666667%;left:auto}.ant-col-xxl-pull-16.ant-col-rtl{right:auto;left:66.66666667%}.ant-col-xxl-offset-16.ant-col-rtl{margin-right:66.66666667%;margin-left:0}.ant-col-xxl-push-17.ant-col-rtl{right:70.83333333%;left:auto}.ant-col-xxl-pull-17.ant-col-rtl{right:auto;left:70.83333333%}.ant-col-xxl-offset-17.ant-col-rtl{margin-right:70.83333333%;margin-left:0}.ant-col-xxl-push-18.ant-col-rtl{right:75%;left:auto}.ant-col-xxl-pull-18.ant-col-rtl{right:auto;left:75%}.ant-col-xxl-offset-18.ant-col-rtl{margin-right:75%;margin-left:0}.ant-col-xxl-push-19.ant-col-rtl{right:79.16666667%;left:auto}.ant-col-xxl-pull-19.ant-col-rtl{right:auto;left:79.16666667%}.ant-col-xxl-offset-19.ant-col-rtl{margin-right:79.16666667%;margin-left:0}.ant-col-xxl-push-20.ant-col-rtl{right:83.33333333%;left:auto}.ant-col-xxl-pull-20.ant-col-rtl{right:auto;left:83.33333333%}.ant-col-xxl-offset-20.ant-col-rtl{margin-right:83.33333333%;margin-left:0}.ant-col-xxl-push-21.ant-col-rtl{right:87.5%;left:auto}.ant-col-xxl-pull-21.ant-col-rtl{right:auto;left:87.5%}.ant-col-xxl-offset-21.ant-col-rtl{margin-right:87.5%;margin-left:0}.ant-col-xxl-push-22.ant-col-rtl{right:91.66666667%;left:auto}.ant-col-xxl-pull-22.ant-col-rtl{right:auto;left:91.66666667%}.ant-col-xxl-offset-22.ant-col-rtl{margin-right:91.66666667%;margin-left:0}.ant-col-xxl-push-23.ant-col-rtl{right:95.83333333%;left:auto}.ant-col-xxl-pull-23.ant-col-rtl{right:auto;left:95.83333333%}.ant-col-xxl-offset-23.ant-col-rtl{margin-right:95.83333333%;margin-left:0}.ant-col-xxl-push-24.ant-col-rtl{right:100%;left:auto}.ant-col-xxl-pull-24.ant-col-rtl{right:auto;left:100%}.ant-col-xxl-offset-24.ant-col-rtl{margin-right:100%;margin-left:0}}.ant-row-rtl{direction:rtl}.ant-col.ant-col-rtl{float:right}.cuk-icon-loading{color:#000}.ant-input-affix-wrapper{position:relative;display:inline-block;width:100%;min-width:0;padding:4px 8px;color:#000a29e6;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s;display:inline-flex}.ant-input-affix-wrapper::-moz-placeholder{opacity:1}.ant-input-affix-wrapper::placeholder{color:#0006}.ant-input-affix-wrapper:placeholder-shown{text-overflow:ellipsis}.ant-input-affix-wrapper:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-input-affix-wrapper:hover{border-right-width:0;border-left-width:1px!important}.ant-input-affix-wrapper:focus,.ant-input-affix-wrapper-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-input-affix-wrapper:focus,.ant-input-rtl .ant-input-affix-wrapper-focused{border-right-width:0;border-left-width:1px!important}.ant-input-affix-wrapper-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-affix-wrapper-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input-affix-wrapper[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-affix-wrapper[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input-affix-wrapper{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-affix-wrapper-lg{padding:6.5px 8px;font-size:16px}.ant-input-affix-wrapper-md{padding:3px 7px;font-size:14px}.ant-input-affix-wrapper-sm{padding:0 8px}.ant-input-affix-wrapper-rtl{direction:rtl}.ant-input-affix-wrapper-disabled .ant-input[disabled]{background:transparent}.ant-input-affix-wrapper>input.ant-input{padding:0;border:none;outline:none}.ant-input-affix-wrapper>input.ant-input:focus{box-shadow:none}.ant-input-affix-wrapper:before{width:0;visibility:hidden;content:"\a0"}.ant-input-prefix,.ant-input-suffix{display:flex;flex:none;align-items:center}.ant-input-prefix{margin-right:8px}.ant-input-affix-wrapper-lg .ant-input-prefix{margin-right:12px}.ant-input-affix-wrapper-md .ant-input-prefix{margin-right:8px}.ant-input-affix-wrapper-sm .ant-input-prefix{margin-right:6px}.ant-input-suffix{margin-left:8px}.ant-input-clear-icon{color:#00000040;font-size:12px;cursor:pointer;transition:color .3s}.ant-input-clear-icon:active{color:#000a29e6}.ant-input-clear-icon+i{margin-left:6px}.ant-input-clear-icon-hidden{visibility:hidden}.ant-input-clear-icon svg{width:16px;height:16px}.ant-input-clear-icon .ant-input-clear-icon{margin-bottom:2px}.ant-input-clear-icon .ant-input-clear-icon-hover{display:none}.ant-input-clear-icon:hover .ant-input-clear-icon-hover{display:block}.ant-input-clear-icon:hover .ant-input-clear-icon{display:none}.ant-input-clear-icon:last-child{margin-right:0}.ant-input-affix-wrapper-textarea-with-clear-btn{padding:0!important;border:0!important}.ant-input-textarea-clear-icon{color:#00000040;font-size:12px;cursor:pointer;transition:color .3s;position:absolute;top:0;right:0;margin:8px 8px 0 0}.ant-input-textarea-clear-icon:active{color:#000a29e6}.ant-input-textarea-clear-icon+i{margin-left:6px}.ant-input-textarea-clear-icon-hidden{visibility:hidden}.ant-input-textarea-clear-icon svg{width:16px;height:16px}.ant-input-textarea-clear-icon .ant-input-clear-icon{margin-bottom:2px}.ant-input-textarea-clear-icon .ant-input-clear-icon-hover{display:none}.ant-input-textarea-clear-icon:hover .ant-input-clear-icon-hover{display:block}.ant-input-textarea-clear-icon:hover .ant-input-clear-icon{display:none}.ant-input-textarea-clear-icon .ant-input-clear-icon{margin-bottom:4px}.ant-input{box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;width:100%;min-width:0;padding:4px 8px;color:#000a29e6;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s}.ant-input::-moz-placeholder{opacity:1}.ant-input::placeholder{color:#0006}.ant-input:placeholder-shown{text-overflow:ellipsis}.ant-input:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-input:hover{border-right-width:0;border-left-width:1px!important}.ant-input:focus,.ant-input-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-input:focus,.ant-input-rtl .ant-input-focused{border-right-width:0;border-left-width:1px!important}.ant-input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-lg{padding:6.5px 8px;font-size:16px}.ant-input-md{padding:3px 7px;font-size:14px}.ant-input-sm{padding:0 8px}.ant-input-rtl{direction:rtl}.ant-input-group{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:table;width:100%;border-collapse:separate;border-spacing:0}.ant-input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.ant-input-group>[class*=col-]{padding-right:8px}.ant-input-group>[class*=col-]:last-child{padding-right:0}.ant-input-group-addon,.ant-input-group-wrap,.ant-input-group>.ant-input{display:table-cell}.ant-input-group-addon:not(:first-child):not(:last-child),.ant-input-group-wrap:not(:first-child):not(:last-child),.ant-input-group>.ant-input:not(:first-child):not(:last-child){border-radius:0}.ant-input-group-addon,.ant-input-group-wrap{width:1px;white-space:nowrap;vertical-align:middle}.ant-input-group-wrap>*{display:block!important}.ant-input-group .ant-input{float:left;width:100%;margin-bottom:0;text-align:inherit}.ant-input-group .ant-input:focus{z-index:1;border-right-width:1px}.ant-input-group .ant-input:hover{z-index:1;border-right-width:1px}.ant-input-group-addon{position:relative;padding:0 8px;color:#23334a;font-weight:400;font-size:14px;text-align:center;background-color:#f1f2f5;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s}.ant-input-group-addon .ant-select{margin:-5px -8px}.ant-input-group-addon .ant-select.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{background-color:inherit;border:1px solid transparent;box-shadow:none}.ant-input-group-addon .ant-select-open .ant-select-selector,.ant-input-group-addon .ant-select-focused .ant-select-selector{color:#0052d9}.ant-input-group-addon>i:only-child:after{position:absolute;top:0;right:0;bottom:0;left:0;content:""}.ant-input-group>.ant-input:first-child,.ant-input-group-addon:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group>.ant-input:first-child .ant-select .ant-select-selector,.ant-input-group-addon:first-child .ant-select .ant-select-selector{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group>.ant-input-affix-wrapper:not(:first-child) .ant-input{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group>.ant-input-affix-wrapper:not(:last-child) .ant-input{border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group-addon:first-child{border-right:0}.ant-input-group-addon:last-child{border-left:0}.ant-input-group>.ant-input:last-child,.ant-input-group-addon:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group>.ant-input:last-child .ant-select .ant-select-selector,.ant-input-group-addon:last-child .ant-select .ant-select-selector{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group-lg .ant-input,.ant-input-group-lg>.ant-input-group-addon{padding:6.5px 8px;font-size:16px}.ant-input-group-sm .ant-input,.ant-input-group-sm>.ant-input-group-addon{padding:0 8px}.ant-input-group-lg .ant-select-single .ant-select-selector{height:40px}.ant-input-group-sm .ant-select-single .ant-select-selector{height:24px}.ant-input-group .ant-input-affix-wrapper:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group .ant-input-affix-wrapper:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.ant-input-group.ant-input-group-compact{display:block}.ant-input-group.ant-input-group-compact:before{display:table;content:""}.ant-input-group.ant-input-group-compact:after{display:table;clear:both;content:""}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child),.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child),.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child){border-right-width:1px}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child):hover,.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child):hover,.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child):hover{z-index:1}.ant-input-group.ant-input-group-compact-addon:not(:first-child):not(:last-child):focus,.ant-input-group.ant-input-group-compact-wrap:not(:first-child):not(:last-child):focus,.ant-input-group.ant-input-group-compact>.ant-input:not(:first-child):not(:last-child):focus{z-index:1}.ant-input-group.ant-input-group-compact>*{display:inline-block;float:none;vertical-align:top;border-radius:0}.ant-input-group.ant-input-group-compact>.ant-input-affix-wrapper{display:inline-flex}.ant-input-group.ant-input-group-compact>.ant-picker-range{display:inline-flex}.ant-input-group.ant-input-group-compact>*:not(:last-child){margin-right:-1px;border-right-width:1px}.ant-input-group.ant-input-group-compact .ant-input{float:none}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input{border-right-width:1px;border-radius:0}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector:hover,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input:hover,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor:hover,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input:hover,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input:hover{z-index:1}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-selector:focus,.ant-input-group.ant-input-group-compact>.ant-calendar-picker .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-cascader-picker .ant-input:focus,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper .ant-mention-editor:focus,.ant-input-group.ant-input-group-compact>.ant-time-picker .ant-time-picker-input:focus,.ant-input-group.ant-input-group-compact>.ant-input-group-wrapper .ant-input:focus{z-index:1}.ant-input-group.ant-input-group-compact>.ant-select-focused{z-index:1}.ant-input-group.ant-input-group-compact>.ant-select>.ant-select-arrow{z-index:1}.ant-input-group.ant-input-group-compact>*:first-child,.ant-input-group.ant-input-group-compact>.ant-select:first-child>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker:first-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:first-child .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker:first-child .ant-time-picker-input{border-top-left-radius:3px;border-bottom-left-radius:3px}.ant-input-group.ant-input-group-compact>*:last-child,.ant-input-group.ant-input-group-compact>.ant-select:last-child>.ant-select-selector,.ant-input-group.ant-input-group-compact>.ant-calendar-picker:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-cascader-picker-focused:last-child .ant-input,.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:last-child .ant-mention-editor,.ant-input-group.ant-input-group-compact>.ant-time-picker:last-child .ant-time-picker-input{border-right-width:1px;border-top-right-radius:3px;border-bottom-right-radius:3px}.ant-input-group.ant-input-group-compact>.ant-select-auto-complete .ant-input{vertical-align:top}.ant-input-group>.ant-input-rtl:first-child,.ant-input-group-rtl .ant-input-group-addon:first-child{border-radius:0 3px 3px 0}.ant-input-group-rtl .ant-input-group-addon:first-child{border-right:1px solid #d9d9d9;border-left:0}.ant-input-group-rtl .ant-input-group-addon:last-child{border-right:0;border-left:1px solid #d9d9d9}.ant-input-group-rtl .ant-input-group>.ant-input:last-child,.ant-input-group-rtl .ant-input-group-addon:last-child{border-radius:3px 0 0 3px}.ant-input-group-rtl.ant-input-group .ant-input-affix-wrapper:not(:first-child){border-radius:3px 0 0 3px}.ant-input-group-rtl.ant-input-group .ant-input-affix-wrapper:not(:last-child){border-radius:0 3px 3px 0}.ant-input-group-rtl.ant-input-group.ant-input-group-compact>*:not(:last-child){margin-right:0;margin-left:-1px;border-left-width:1px}.ant-input-group-rtl.ant-input-group.ant-input-group-compact>*:first-child,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-select:first-child>.ant-select-selector,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-calendar-picker:first-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:first-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-cascader-picker:first-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:first-child .ant-mention-editor,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-time-picker:first-child .ant-time-picker-input{border-radius:0 3px 3px 0}.ant-input-group-rtl.ant-input-group.ant-input-group-compact>*:last-child,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-select:last-child>.ant-select-selector,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-calendar-picker:last-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-select-auto-complete:last-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-cascader-picker:last-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-cascader-picker-focused:last-child .ant-input,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-mention-wrapper:last-child .ant-mention-editor,.ant-input-group-rtl.ant-input-group.ant-input-group-compact>.ant-time-picker:last-child .ant-time-picker-input{border-left-width:1px;border-radius:3px 0 0 3px}.ant-input-group-wrapper{display:inline-block;width:100%;text-align:start;vertical-align:top}.ant-input-password-icon{color:#adbacc;cursor:pointer;transition:all .3s}.ant-input-password-icon:hover{color:#202d40}.ant-input[type=color]{height:32px}.ant-input[type=color].ant-input-lg{height:40px}.ant-input[type=color].ant-input-md{height:30px}.ant-input[type=color].ant-input-sm{height:24px;padding-top:3px;padding-bottom:3px}.ant-input::placeholder{color:#0006;font-family:PingFang SC,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.ant-input-search-icon{padding:0 9px}.ant-input-search-icon:before{transform:translate(-10px)}.ant-input-search-icon:after{width:32px}.ant-input-affix-wrapper-lg .ant-input-search-icon{padding:0 12px}.ant-input-affix-wrapper-lg .ant-input-search-icon:before{transform:translate(-13px)}.ant-input-affix-wrapper-lg .ant-input-search-icon:after{width:40px}.ant-input-affix-wrapper-md .ant-input-search-icon{padding:0 8px}.ant-input-affix-wrapper-md .ant-input-search-icon:before{transform:translate(-9px)}.ant-input-affix-wrapper-md .ant-input-search-icon:after{width:30px}.ant-input-affix-wrapper-sm .ant-input-search-icon{padding:0 6px}.ant-input-affix-wrapper-sm .ant-input-search-icon:before{transform:translate(-7px)}.ant-input-affix-wrapper-sm .ant-input-search-icon:after{width:24px}.ant-input-search-icon{margin-left:.5em;color:#adbacc;cursor:pointer;transition:all .3s}.ant-input-search-icon:hover{color:#000000d9}.ant-input-search-icon:before{position:absolute;top:0;bottom:0;display:block;transition:all .3s;content:""}.ant-input-search-icon:after{position:absolute;top:0;right:0;bottom:0;content:""}.ant-input-search-icon.cuk2-icon-loading{color:#0052d9}.ant-input-search:not(.ant-input-search-enter-button){padding-right:0}.ant-input-search-enter-button input{border-right:0}.ant-input-search-enter-button input:hover,.ant-input-search-enter-button input:focus{border-color:#2575e6}.ant-input-search-enter-button.ant-input-affix-wrapper{border-right:0}.ant-input-search-enter-button+.ant-input-group-addon,.ant-input-search-enter-button input+.ant-input-group-addon{padding:0;border:0}.ant-input-search-enter-button+.ant-input-group-addon .ant-input-search-button,.ant-input-search-enter-button input+.ant-input-group-addon .ant-input-search-button{border-top-left-radius:0;border-bottom-left-radius:0}.ant-input-group-wrapper-rtl,.ant-input-group-rtl{direction:rtl}.ant-input-affix-wrapper.ant-input-affix-wrapper-rtl>input.ant-input{border:none;outline:none}.ant-input-affix-wrapper-rtl .ant-input-prefix{margin:0 0 0 8px}.ant-input-affix-wrapper-rtl .ant-input-suffix{margin:0 8px 0 0}.ant-input-affix-wrapper-rtl .ant-input-clear-icon:last-child{margin-right:8px;margin-left:0}.ant-input-affix-wrapper-rtl .ant-input-textarea-clear-icon{right:auto;left:0;margin:8px 0 0 8px}.ant-input-search-rtl{direction:rtl}.ant-input-search-rtl .ant-input-search-icon{margin-right:.5em;margin-left:0}.ant-input-search-rtl .ant-input-search-icon:before{border-left:none}.ant-input-search-rtl .ant-input-search-icon:after{right:auto;left:0;border-right:1px solid #d9d9d9;transition:all .3s}.ant-input-search-rtl.ant-input-search:not(.ant-input-search-enter-button){padding-right:8px;padding-left:0}.ant-input-search-rtl.ant-input-search-enter-button input{border-right:1px solid #d9d9d9;border-left:0}.ant-input-search-rtl.ant-input-search-enter-button input:hover,.ant-input-search-rtl.ant-input-search-enter-button input:focus{border-color:#2575e6}.ant-input-search-rtl.ant-input-search-enter-button.ant-input-affix-wrapper{border-right:1px solid #d9d9d9;border-left:0}.ant-input-search-rtl.ant-input-search-enter-button.ant-input-affix-wrapper:hover,.ant-input-search-rtl.ant-input-search-enter-button.ant-input-affix-wrapper:focus{border-color:#2575e6}.ant-input-search-rtl.ant-input-search-enter-button+.ant-input-group-addon .ant-input-search-button,.ant-input-search-rtl.ant-input-search-enter-button input+.ant-input-group-addon .ant-input-search-button{width:100%;border-radius:3px 0 0 3px}.ant-input-number{box-sizing:border-box;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";position:relative;width:100%;min-width:0;color:#000a29e6;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;transition:all .3s;display:inline-block;width:100px;margin:0;padding:0;border:1px solid #d9d9d9;border-radius:3px}.ant-input-number::-moz-placeholder{opacity:1}.ant-input-number::placeholder{color:#0006}.ant-input-number:placeholder-shown{text-overflow:ellipsis}.ant-input-rtl .ant-input-number:hover{border-right-width:0;border-left-width:1px!important}.ant-input-number:focus,.ant-input-number-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-input-number:focus,.ant-input-rtl .ant-input-number-focused{border-right-width:0;border-left-width:1px!important}.ant-input-number[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-number[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-input-number{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-input-number-lg{padding:6.5px 8px;font-size:16px}.ant-input-number-md{padding:3px 7px;font-size:14px}.ant-input-number-sm{padding:0 8px}.ant-input-number-handler{position:relative;display:block;width:100%;height:50%;overflow:hidden;color:#000a2999;font-weight:700;line-height:0;text-align:center;transition:all .1s linear}.ant-input-number-handler:active{background:#f4f4f4}.ant-input-number-handler:hover .ant-input-number-handler-up-inner,.ant-input-number-handler:hover .ant-input-number-handler-down-inner{color:#2575e6}.ant-input-number-handler-up-inner,.ant-input-number-handler-down-inner{display:inline-block;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;right:4px;width:12px;height:12px;color:#000a2999;line-height:12px;transition:all .1s linear;user-select:none}.ant-input-number-handler-up-inner>*,.ant-input-number-handler-down-inner>*{line-height:1}.ant-input-number-handler-up-inner svg,.ant-input-number-handler-down-inner svg{display:inline-block}.ant-input-number-handler-up-inner:before,.ant-input-number-handler-down-inner:before{display:none}.ant-input-number-handler-up-inner .ant-input-number-handler-up-inner-icon,.ant-input-number-handler-up-inner .ant-input-number-handler-down-inner-icon,.ant-input-number-handler-down-inner .ant-input-number-handler-up-inner-icon,.ant-input-number-handler-down-inner .ant-input-number-handler-down-inner-icon{display:block}.ant-input-number:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-number:hover+.ant-form-item-children-icon{opacity:0;transition:opacity .24s linear .24s}.ant-input-number-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-input-number-focused{border-right-width:0;border-left-width:1px!important}.ant-input-number-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-input-number-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-input-number-disabled .ant-input-number-input{cursor:not-allowed}.ant-input-number-disabled .ant-input-number-handler-wrap,.ant-input-number-readonly .ant-input-number-handler-wrap{display:none}.ant-input-number-input{width:100%;height:30px;padding:0 7px;text-align:left;background-color:transparent;border:0;border-radius:3px;outline:0;transition:all .3s linear;-moz-appearance:textfield!important}.ant-input-number-input::-moz-placeholder{opacity:1}.ant-input-number-input::placeholder{color:#0006}.ant-input-number-input:placeholder-shown{text-overflow:ellipsis}.ant-input-number-input[type=number]::-webkit-inner-spin-button,.ant-input-number-input[type=number]::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.ant-input-number-lg{padding:0;font-size:16px}.ant-input-number-lg input{height:38px}.ant-input-number-md{padding:0;font-size:14px}.ant-input-number-md input{height:28px}.ant-input-number-sm{padding:0}.ant-input-number-sm input{height:22px;padding:0 7px}.ant-input-number-sm .ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-up-inner,.ant-input-number-sm .ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-down-inner{font-size:8px}.ant-input-number-handler-wrap{position:absolute;top:0;right:0;width:17px;height:100%;background:#fff;border-left:1px solid #d9d9d9;border-radius:0 3px 3px 0;opacity:0;transition:opacity .24s linear .1s}.ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-up-inner,.ant-input-number-handler-wrap .ant-input-number-handler .ant-input-number-handler-down-inner{min-width:auto;margin-right:-2px;font-size:12px}.ant-input-number-handler-wrap:hover .ant-input-number-handler{height:40%}.ant-input-number:hover .ant-input-number-handler-wrap{opacity:1}.ant-input-number-handler-up{border-top-right-radius:3px;cursor:pointer}.ant-input-number-handler-up-inner{top:50%;margin-top:-5px;text-align:center}.ant-input-number-handler-up:hover{height:60%!important}.ant-input-number-handler-down{top:0;border-top:1px solid #d9d9d9;border-bottom-right-radius:3px;cursor:pointer}.ant-input-number-handler-down-inner{top:50%;text-align:center;transform:translateY(-50%)}.ant-input-number-handler-down:hover{height:60%!important}.ant-input-number-handler-up-disabled,.ant-input-number-handler-down-disabled{cursor:not-allowed}.ant-input-number-handler-up-disabled:hover .ant-input-number-handler-up-inner,.ant-input-number-handler-down-disabled:hover .ant-input-number-handler-down-inner{color:#00000040}.ant-input-number-rtl{direction:rtl}.ant-input-number-rtl .ant-input-number-handler-wrap{right:auto;left:0;border-right:1px solid #d9d9d9;border-left:0;border-radius:3px 0 0 3px}.ant-input-number-rtl .ant-input-number-input{direction:ltr;text-align:right}.ant-layout{display:flex;flex:auto;flex-direction:column;min-height:0;background:#f0f2f5}.ant-layout,.ant-layout *{box-sizing:border-box}.ant-layout.ant-layout-has-sider{flex-direction:row}.ant-layout.ant-layout-has-sider>.ant-layout,.ant-layout.ant-layout-has-sider>.ant-layout-content{overflow-x:hidden}.ant-layout-header,.ant-layout-footer{flex:0 0 auto}.ant-layout-header{height:64px;padding:0 50px;color:#000a29e6;line-height:64px;background:#001529}.ant-layout-footer{padding:24px 50px;color:#000a29e6;font-size:14px;background:#f0f2f5}.ant-layout-content{flex:auto;min-height:0}.ant-layout-sider{position:relative;min-width:0;background:#001529;transition:all .2s}.ant-layout-sider-children{height:100%;margin-top:-.1px;padding-top:.1px}.ant-layout-sider-has-trigger{padding-bottom:48px}.ant-layout-sider-right{order:1}.ant-layout-sider-trigger{position:fixed;bottom:0;z-index:1;height:48px;color:#fff;line-height:48px;text-align:center;background:#002140;cursor:pointer;transition:all .2s}.ant-layout-sider-zero-width>*{overflow:hidden}.ant-layout-sider-zero-width-trigger{position:absolute;top:64px;right:-36px;z-index:1;width:36px;height:42px;color:#fff;font-size:18px;line-height:42px;text-align:center;background:#001529;border-radius:0 3px 3px 0;cursor:pointer;transition:background .3s ease}.ant-layout-sider-zero-width-trigger:hover{background:#192c3e}.ant-layout-sider-zero-width-trigger-right{left:-36px;border-radius:3px 0 0 3px}.ant-layout-sider-light{background:#fff}.ant-layout-sider-light .ant-layout-sider-trigger,.ant-layout-sider-light .ant-layout-sider-zero-width-trigger{color:#000a29e6;background:#fff}.ant-layout-rtl{direction:rtl}.ant-list{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative}.ant-list *{outline:none}.ant-list-pagination{margin-top:24px;text-align:right}.ant-list-pagination .ant-pagination-options{text-align:left}.ant-list-more{margin-top:12px;text-align:center}.ant-list-more button{padding-right:32px;padding-left:32px}.ant-list-spin{min-height:40px;text-align:center}.ant-list-empty-text{padding:16px;color:#00000040;font-size:14px;text-align:center}.ant-list-items{margin:0;padding:0;list-style:none}.ant-list-item{display:flex;align-items:center;justify-content:space-between;padding:12px 0}.ant-list-item-content{color:#000a29e6}.ant-list-item-meta{display:flex;flex:1;align-items:flex-start;font-size:0}.ant-list-item-meta-avatar{margin-right:16px}.ant-list-item-meta-content{flex:1 0}.ant-list-item-meta-title{margin-bottom:4px;color:#000a29e6;font-size:14px;line-height:1.5715}.ant-list-item-meta-title>a{color:#000a29e6;transition:all .3s}.ant-list-item-meta-title>a:hover{color:#0052d9}.ant-list-item-meta-description{color:#000a2999;font-size:14px;line-height:1.5715}.ant-list-item-action{flex:0 0 auto;margin-left:48px;padding:0;font-size:0;list-style:none}.ant-list-item-action>li{position:relative;display:inline-block;padding:0 8px;color:#000a2999;font-size:14px;line-height:1.5715;text-align:center;cursor:pointer}.ant-list-item-action>li:first-child{padding-left:0}.ant-list-item-action-split{position:absolute;top:50%;right:0;width:1px;height:14px;margin-top:-7px;background-color:#f0f0f0}.ant-list-header,.ant-list-footer{background:transparent}.ant-list-header,.ant-list-footer{padding-top:12px;padding-bottom:12px}.ant-list-empty{padding:16px 0;color:#000a2999;font-size:12px;text-align:center}.ant-list-split .ant-list-item{border-bottom:1px solid #f0f0f0}.ant-list-split .ant-list-item:last-child{border-bottom:none}.ant-list-split .ant-list-header{border-bottom:1px solid #f0f0f0}.ant-list-split.ant-list-empty .ant-list-footer{border-top:1px solid #f0f0f0}.ant-list-loading .ant-list-spin-nested-loading{min-height:32px}.ant-list-split.ant-list-something-after-last-item .ant-spin-container>.ant-list-items>.ant-list-item:last-child{border-bottom:1px solid #f0f0f0}.ant-list-lg .ant-list-item{padding:16px 24px}.ant-list-sm .ant-list-item{padding:8px 16px}.ant-list-vertical .ant-list-item{align-items:initial}.ant-list-vertical .ant-list-item-main{display:block;flex:1}.ant-list-vertical .ant-list-item-extra{margin-left:40px}.ant-list-vertical .ant-list-item-meta{margin-bottom:16px}.ant-list-vertical .ant-list-item-meta-title{margin-bottom:12px;color:#000a29e6;font-size:16px;line-height:24px}.ant-list-vertical .ant-list-item-action{margin-top:16px;margin-left:auto}.ant-list-vertical .ant-list-item-action>li{padding:0 16px}.ant-list-vertical .ant-list-item-action>li:first-child{padding-left:0}.ant-list-grid .ant-col>.ant-list-item{display:block;max-width:100%;margin-bottom:16px;padding-top:0;padding-bottom:0;border-bottom:none}.ant-list-item-no-flex{display:block}.ant-list:not(.ant-list-vertical) .ant-list-item-no-flex .ant-list-item-action{float:right}.ant-list-bordered{border:1px solid #d9d9d9;border-radius:3px}.ant-list-bordered .ant-list-header,.ant-list-bordered .ant-list-footer,.ant-list-bordered .ant-list-item{padding-right:24px;padding-left:24px}.ant-list-bordered .ant-list-pagination{margin:16px 24px}.ant-list-bordered.ant-list-sm .ant-list-item,.ant-list-bordered.ant-list-sm .ant-list-header,.ant-list-bordered.ant-list-sm .ant-list-footer{padding:8px 16px}.ant-list-bordered.ant-list-lg .ant-list-item,.ant-list-bordered.ant-list-lg .ant-list-header,.ant-list-bordered.ant-list-lg .ant-list-footer{padding:16px 24px}@media screen and (max-width: 768px){.ant-list-item-action,.ant-list-vertical .ant-list-item-extra{margin-left:24px}}@media screen and (max-width: 576px){.ant-list-item{flex-wrap:wrap}.ant-list-item-action{margin-left:12px}.ant-list-vertical .ant-list-item{flex-wrap:wrap-reverse}.ant-list-vertical .ant-list-item-main{min-width:220px}.ant-list-vertical .ant-list-item-extra{margin:auto auto 16px}}.ant-list-rtl{direction:rtl;text-align:right}.ant-list-rtl .ReactVirtualized__List .ant-list-item{direction:rtl}.ant-list-rtl .ant-list-pagination{text-align:left}.ant-list-rtl .ant-list-item-meta-avatar{margin-right:0;margin-left:16px}.ant-list-rtl .ant-list-item-action{margin-right:48px;margin-left:0}.ant-list-rtl .ant-list-item-action>li:first-child{padding-right:0;padding-left:8px}.ant-list-rtl .ant-list-item-action-split{right:auto;left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-extra{margin-right:40px;margin-left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-action{margin-right:auto}.ant-list-rtl .ant-list-vertical .ant-list-item-action>li:first-child{padding-right:0;padding-left:16px}.ant-list-rtl .ant-list:not(.ant-list-vertical) .ant-list-item-no-flex .ant-list-item-action{float:left}@media screen and (max-width: 768px){.ant-list-rtl .ant-list-item-action,.ant-list-rtl .ant-list-vertical .ant-list-item-extra{margin-right:24px;margin-left:0}}@media screen and (max-width: 576px){.ant-list-rtl .ant-list-item-action{margin-right:22px;margin-left:0}.ant-list-rtl.ant-list-vertical .ant-list-item-extra{margin:auto auto 16px}}.ant-mentions{box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";width:100%;min-width:0;color:#000a29e6;font-size:14px;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s;position:relative;display:inline-block;height:auto;padding:0;overflow:hidden;line-height:1.5715;white-space:pre-wrap;vertical-align:bottom}.ant-mentions::-moz-placeholder{opacity:1}.ant-mentions::placeholder{color:#0006}.ant-mentions:placeholder-shown{text-overflow:ellipsis}.ant-mentions:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-mentions:hover{border-right-width:0;border-left-width:1px!important}.ant-mentions:focus,.ant-mentions-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-mentions:focus,.ant-input-rtl .ant-mentions-focused{border-right-width:0;border-left-width:1px!important}.ant-mentions-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-mentions[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-mentions{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-mentions-lg{padding:6.5px 8px;font-size:16px}.ant-mentions-md{padding:3px 7px;font-size:14px}.ant-mentions-sm{padding:0 8px}.ant-mentions-disabled>textarea{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-mentions-disabled>textarea:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-mentions-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-mentions-focused{border-right-width:0;border-left-width:1px!important}.ant-mentions>textarea,.ant-mentions-measure{min-height:30px;margin:0;padding:4px 8px;overflow:inherit;overflow-x:hidden;overflow-y:auto;font-weight:inherit;font-size:inherit;font-family:inherit;font-style:inherit;font-variant:inherit;font-size-adjust:inherit;font-stretch:inherit;line-height:inherit;direction:inherit;letter-spacing:inherit;white-space:inherit;text-align:inherit;vertical-align:top;word-wrap:break-word;word-break:inherit;tab-size:inherit}.ant-mentions>textarea{width:100%;border:none;outline:none;resize:none}.ant-mentions>textarea::-moz-placeholder{opacity:1}.ant-mentions>textarea::placeholder{color:#0006}.ant-mentions>textarea:placeholder-shown{text-overflow:ellipsis}.ant-mentions>textarea:read-only{cursor:default}.ant-mentions-measure{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;color:transparent;pointer-events:none}.ant-mentions-measure>span{display:inline-block;min-height:1em}.ant-mentions-dropdown{margin:0;padding:0;color:#000a29e6;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:-9999px;left:-9999px;z-index:1050;box-sizing:border-box;font-size:14px;font-variant:initial;background-color:#fff;border-radius:3px;outline:none;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-mentions-dropdown-hidden{display:none}.ant-mentions-dropdown-menu{max-height:250px;margin-bottom:0;padding-left:0;overflow:auto;list-style:none;outline:none}.ant-mentions-dropdown-menu-item{position:relative;display:block;min-width:100px;padding:5px 8px;overflow:hidden;color:#000a29e6;font-weight:400;line-height:1.5715;white-space:nowrap;text-overflow:ellipsis;cursor:pointer;transition:background .3s ease}.ant-mentions-dropdown-menu-item:hover{background-color:#f3f3f3}.ant-mentions-dropdown-menu-item:first-child{border-radius:3px 3px 0 0}.ant-mentions-dropdown-menu-item:last-child{border-radius:0 0 3px 3px}.ant-mentions-dropdown-menu-item-disabled{color:#00000040;cursor:not-allowed}.ant-mentions-dropdown-menu-item-disabled:hover{color:#00000040;background-color:#fff;cursor:not-allowed}.ant-mentions-dropdown-menu-item-selected{color:#000a29e6;font-weight:600;background-color:#f1f2f5}.ant-mentions-dropdown-menu-item-active{background-color:#f3f3f3}.ant-mentions-rtl{direction:rtl}.ant-menu{box-sizing:border-box;margin:0;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:"tnum";padding:0;color:#000a29e6;font-size:14px;line-height:0;list-style:none;background:#fff;outline:none;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d;transition:background .3s,width .2s}.ant-menu:before{display:table;content:""}.ant-menu:after{display:table;clear:both;content:""}.ant-menu ul,.ant-menu ol{margin:0;padding:0;list-style:none}.ant-menu-hidden{display:none}.ant-menu-item-group-title{height:1.5715;padding:8px 16px;color:#000a2999;font-size:14px;line-height:1.5715;transition:all .3s}.ant-menu-submenu,.ant-menu-submenu-inline{transition:border-color .3s cubic-bezier(.645,.045,.355,1),background .3s cubic-bezier(.645,.045,.355,1),padding .15s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-selected{color:#0052d9}.ant-menu-item:active,.ant-menu-submenu-title:active{background:#e6f4ff}.ant-menu-submenu .ant-menu-sub{cursor:initial;transition:background .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-item a{color:#000a29e6}.ant-menu-item a:hover{color:#0052d9}.ant-menu-item a:before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:transparent;content:""}.ant-menu-item>.ant-badge a{color:#000a29e6}.ant-menu-item>.ant-badge a:hover{color:#0052d9}.ant-menu-item-divider{height:1px;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-menu-item:hover,.ant-menu-item-active,.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,.ant-menu-submenu-active,.ant-menu-submenu-title:hover{color:#0052d9}.ant-menu-horizontal .ant-menu-item,.ant-menu-horizontal .ant-menu-submenu{margin-top:-1px}.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-submenu .ant-menu-submenu-title:hover{background-color:transparent}.ant-menu-item-selected,.ant-menu-item-selected a,.ant-menu-item-selected a:hover{color:#0052d9}.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{background-color:#e6f4ff}.ant-menu-inline,.ant-menu-vertical,.ant-menu-vertical-left{border-right:1px solid #f0f0f0}.ant-menu-vertical-right{border-left:1px solid #f0f0f0}.ant-menu-vertical.ant-menu-sub,.ant-menu-vertical-left.ant-menu-sub,.ant-menu-vertical-right.ant-menu-sub{min-width:160px;max-height:calc(100vh - 100px);padding:0;overflow:hidden;border-right:0;transform-origin:0 0}.ant-menu-vertical.ant-menu-sub:not(.zoom-big-enter-active):not(.zoom-big-leave-active),.ant-menu-vertical-left.ant-menu-sub:not(.zoom-big-enter-active):not(.zoom-big-leave-active),.ant-menu-vertical-right.ant-menu-sub:not(.zoom-big-enter-active):not(.zoom-big-leave-active){overflow-x:hidden;overflow-y:auto}.ant-menu-vertical.ant-menu-sub .ant-menu-item,.ant-menu-vertical-left.ant-menu-sub .ant-menu-item,.ant-menu-vertical-right.ant-menu-sub .ant-menu-item{left:0;margin-left:0;border-right:0}.ant-menu-vertical.ant-menu-sub .ant-menu-item:after,.ant-menu-vertical-left.ant-menu-sub .ant-menu-item:after,.ant-menu-vertical-right.ant-menu-sub .ant-menu-item:after{border-right:0}.ant-menu-vertical.ant-menu-sub>.ant-menu-item,.ant-menu-vertical-left.ant-menu-sub>.ant-menu-item,.ant-menu-vertical-right.ant-menu-sub>.ant-menu-item,.ant-menu-vertical.ant-menu-sub>.ant-menu-submenu,.ant-menu-vertical-left.ant-menu-sub>.ant-menu-submenu,.ant-menu-vertical-right.ant-menu-sub>.ant-menu-submenu{transform-origin:0 0}.ant-menu-horizontal.ant-menu-sub{min-width:114px}.ant-menu-item,.ant-menu-submenu-title{position:relative;display:block;margin:0;padding:0 20px;white-space:nowrap;cursor:pointer;transition:color .3s cubic-bezier(.645,.045,.355,1),border-color .3s cubic-bezier(.645,.045,.355,1),background .3s cubic-bezier(.645,.045,.355,1),padding .15s cubic-bezier(.645,.045,.355,1)}.ant-menu-item .anticon,.ant-menu-submenu-title .anticon{min-width:14px;margin-right:10px;font-size:14px;transition:font-size .15s cubic-bezier(.215,.61,.355,1),margin .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-item .anticon+span,.ant-menu-submenu-title .anticon+span{opacity:1;transition:opacity .3s cubic-bezier(.645,.045,.355,1),width .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-item.ant-menu-item-only-child>.anticon,.ant-menu-submenu-title.ant-menu-item-only-child>.anticon{margin-right:0}.ant-menu>.ant-menu-item-divider{height:1px;margin:1px 0;padding:0;overflow:hidden;line-height:0;background-color:#f0f0f0}.ant-menu-submenu-popup{position:absolute;z-index:1050;border-radius:3px;box-shadow:none}.ant-menu-submenu-popup:before{position:absolute;top:-7px;right:0;bottom:0;left:0;width:100%;height:100%;opacity:.0001;content:" "}.ant-menu-submenu-placement-rightTop:before{top:0;left:-7px}.ant-menu-submenu>.ant-menu{background-color:#fff;border-radius:3px}.ant-menu-submenu>.ant-menu-submenu-title:after{transition:transform .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-popup>.ant-menu{background-color:#fff}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow{position:absolute;top:50%;right:16px;width:10px;transition:transform .3s cubic-bezier(.645,.045,.355,1)}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{position:absolute;width:6px;height:1.5px;background-image:linear-gradient(to right,rgba(0,10,41,.9),rgba(0,10,41,.9));border-radius:3px;transition:background .3s cubic-bezier(.645,.045,.355,1),transform .3s cubic-bezier(.645,.045,.355,1),top .3s cubic-bezier(.645,.045,.355,1);content:""}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(45deg) translateY(-2px)}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(-45deg) translateY(2px)}.ant-menu-submenu-vertical>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:after,.ant-menu-submenu-inline>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:before,.ant-menu-submenu-inline>.ant-menu-submenu-title:hover .ant-menu-submenu-arrow:before{background:linear-gradient(to right,#0052d9,#0052d9)}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(45deg) translateY(-2px)}.ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(-45deg) translateY(2px)}.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(-45deg) translate(2px)}.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(45deg) translate(-2px)}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow{transform:translateY(-2px)}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(-45deg) translate(-2px)}.ant-menu-submenu-open.ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(45deg) translate(2px)}.ant-menu-vertical .ant-menu-submenu-selected,.ant-menu-vertical-left .ant-menu-submenu-selected,.ant-menu-vertical-right .ant-menu-submenu-selected,.ant-menu-vertical .ant-menu-submenu-selected a,.ant-menu-vertical-left .ant-menu-submenu-selected a,.ant-menu-vertical-right .ant-menu-submenu-selected a{color:#0052d9}.ant-menu-horizontal{line-height:46px;white-space:nowrap;border:0;border-bottom:1px solid #f0f0f0;box-shadow:none}.ant-menu-horizontal>.ant-menu-item,.ant-menu-horizontal>.ant-menu-submenu{position:relative;top:1px;display:inline-block;vertical-align:bottom;border-bottom:2px solid transparent}.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu:hover,.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-submenu-active,.ant-menu-horizontal>.ant-menu-item-open,.ant-menu-horizontal>.ant-menu-submenu-open,.ant-menu-horizontal>.ant-menu-item-selected,.ant-menu-horizontal>.ant-menu-submenu-selected{color:#0052d9;border-bottom:2px solid #0052d9}.ant-menu-horizontal>.ant-menu-item a{color:#000a29e6}.ant-menu-horizontal>.ant-menu-item a:hover{color:#0052d9}.ant-menu-horizontal>.ant-menu-item a:before{bottom:-2px}.ant-menu-horizontal>.ant-menu-item-selected a{color:#0052d9}.ant-menu-horizontal:after{display:block;clear:both;height:0;content:" "}.ant-menu-vertical .ant-menu-item,.ant-menu-vertical-left .ant-menu-item,.ant-menu-vertical-right .ant-menu-item,.ant-menu-inline .ant-menu-item{position:relative}.ant-menu-vertical .ant-menu-item:after,.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-vertical-right .ant-menu-item:after,.ant-menu-inline .ant-menu-item:after{position:absolute;top:0;right:0;bottom:0;border-right:3px solid #0052d9;transform:scaleY(.0001);opacity:0;transition:transform .15s cubic-bezier(.215,.61,.355,1),opacity .15s cubic-bezier(.215,.61,.355,1);content:""}.ant-menu-vertical .ant-menu-item,.ant-menu-vertical-left .ant-menu-item,.ant-menu-vertical-right .ant-menu-item,.ant-menu-inline .ant-menu-item,.ant-menu-vertical .ant-menu-submenu-title,.ant-menu-vertical-left .ant-menu-submenu-title,.ant-menu-vertical-right .ant-menu-submenu-title,.ant-menu-inline .ant-menu-submenu-title{height:40px;margin-top:4px;margin-bottom:4px;padding:0 16px;overflow:hidden;line-height:40px;text-overflow:ellipsis}.ant-menu-vertical .ant-menu-submenu,.ant-menu-vertical-left .ant-menu-submenu,.ant-menu-vertical-right .ant-menu-submenu,.ant-menu-inline .ant-menu-submenu{padding-bottom:.02px}.ant-menu-vertical .ant-menu-item:not(:last-child),.ant-menu-vertical-left .ant-menu-item:not(:last-child),.ant-menu-vertical-right .ant-menu-item:not(:last-child),.ant-menu-inline .ant-menu-item:not(:last-child){margin-bottom:8px}.ant-menu-vertical>.ant-menu-item,.ant-menu-vertical-left>.ant-menu-item,.ant-menu-vertical-right>.ant-menu-item,.ant-menu-inline>.ant-menu-item,.ant-menu-vertical>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-vertical-left>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-vertical-right>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title{height:40px;line-height:40px}.ant-menu-vertical .ant-menu-submenu-title{padding-right:34px}.ant-menu-inline{width:100%}.ant-menu-inline .ant-menu-selected:after,.ant-menu-inline .ant-menu-item-selected:after{transform:scaleY(1);opacity:1;transition:transform .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1)}.ant-menu-inline .ant-menu-item,.ant-menu-inline .ant-menu-submenu-title{width:calc(100% + 1px)}.ant-menu-inline .ant-menu-submenu-title{padding-right:34px}.ant-menu-inline-collapsed{width:80px}.ant-menu-inline-collapsed>.ant-menu-item,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title,.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title{left:0;padding:0 32px;text-overflow:clip}.ant-menu-inline-collapsed>.ant-menu-item .ant-menu-submenu-arrow,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .ant-menu-submenu-arrow,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .ant-menu-submenu-arrow{display:none}.ant-menu-inline-collapsed>.ant-menu-item .anticon,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .anticon,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .anticon,.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .anticon{margin:0;font-size:16px;line-height:40px}.ant-menu-inline-collapsed>.ant-menu-item .anticon+span,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-item .anticon+span,.ant-menu-inline-collapsed>.ant-menu-item-group>.ant-menu-item-group-list>.ant-menu-submenu>.ant-menu-submenu-title .anticon+span,.ant-menu-inline-collapsed>.ant-menu-submenu>.ant-menu-submenu-title .anticon+span{display:inline-block;max-width:0;opacity:0}.ant-menu-inline-collapsed .anticon{display:inline-block}.ant-menu-inline-collapsed-tooltip{pointer-events:none}.ant-menu-inline-collapsed-tooltip .anticon{display:none}.ant-menu-inline-collapsed-tooltip a{color:#ffffffd9}.ant-menu-inline-collapsed .ant-menu-item-group-title{padding-right:4px;padding-left:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-menu-item-group-list{margin:0;padding:0}.ant-menu-item-group-list .ant-menu-item,.ant-menu-item-group-list .ant-menu-submenu-title{padding:0 16px 0 28px}.ant-menu-root.ant-menu-vertical,.ant-menu-root.ant-menu-vertical-left,.ant-menu-root.ant-menu-vertical-right,.ant-menu-root.ant-menu-inline{box-shadow:none}.ant-menu-sub.ant-menu-inline{padding:0;border:0;border-radius:0;box-shadow:none}.ant-menu-sub.ant-menu-inline>.ant-menu-item,.ant-menu-sub.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title{height:40px;line-height:40px;list-style-position:inside;list-style-type:disc}.ant-menu-sub.ant-menu-inline .ant-menu-item-group-title{padding-left:32px}.ant-menu-item-disabled,.ant-menu-submenu-disabled{color:#00000040!important;background:none;border-color:transparent!important;cursor:not-allowed}.ant-menu-item-disabled a,.ant-menu-submenu-disabled a{color:#00000040!important;pointer-events:none}.ant-menu-item-disabled>.ant-menu-submenu-title,.ant-menu-submenu-disabled>.ant-menu-submenu-title{color:#00000040!important;cursor:not-allowed}.ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after{background:rgba(0,0,0,.25)!important}.ant-layout-header .ant-menu{line-height:inherit}.ant-menu.ant-menu-dark,.ant-menu-dark .ant-menu-sub{color:#ffffffa6;background:#001529}.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow{opacity:.45;transition:all .3s}.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu.ant-menu-dark .ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-sub .ant-menu-submenu-title .ant-menu-submenu-arrow:before{background:#fff}.ant-menu-dark.ant-menu-submenu-popup{background:transparent}.ant-menu-dark .ant-menu-inline.ant-menu-sub{background:#000c17}.ant-menu-dark.ant-menu-horizontal{border-bottom:0}.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu{top:0;margin-top:0;border-color:#001529;border-bottom:0}.ant-menu-dark.ant-menu-horizontal>.ant-menu-item>a:before{bottom:0}.ant-menu-dark .ant-menu-item,.ant-menu-dark .ant-menu-item-group-title,.ant-menu-dark .ant-menu-item>a,.ant-menu-dark .ant-menu-item>span>a{color:#ffffffa6}.ant-menu-dark.ant-menu-inline,.ant-menu-dark.ant-menu-vertical,.ant-menu-dark.ant-menu-vertical-left,.ant-menu-dark.ant-menu-vertical-right{border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item,.ant-menu-dark.ant-menu-vertical .ant-menu-item,.ant-menu-dark.ant-menu-vertical-left .ant-menu-item,.ant-menu-dark.ant-menu-vertical-right .ant-menu-item{left:0;margin-left:0;border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-dark.ant-menu-vertical-right .ant-menu-item:after{border-right:0}.ant-menu-dark.ant-menu-inline .ant-menu-item,.ant-menu-dark.ant-menu-inline .ant-menu-submenu-title{width:100%}.ant-menu-dark .ant-menu-item:hover,.ant-menu-dark .ant-menu-item-active,.ant-menu-dark .ant-menu-submenu-active,.ant-menu-dark .ant-menu-submenu-open,.ant-menu-dark .ant-menu-submenu-selected,.ant-menu-dark .ant-menu-submenu-title:hover{color:#fff;background-color:transparent}.ant-menu-dark .ant-menu-item:hover>a,.ant-menu-dark .ant-menu-item-active>a,.ant-menu-dark .ant-menu-submenu-active>a,.ant-menu-dark .ant-menu-submenu-open>a,.ant-menu-dark .ant-menu-submenu-selected>a,.ant-menu-dark .ant-menu-submenu-title:hover>a,.ant-menu-dark .ant-menu-item:hover>span>a,.ant-menu-dark .ant-menu-item-active>span>a,.ant-menu-dark .ant-menu-submenu-active>span>a,.ant-menu-dark .ant-menu-submenu-open>span>a,.ant-menu-dark .ant-menu-submenu-selected>span>a,.ant-menu-dark .ant-menu-submenu-title:hover>span>a{color:#fff}.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow{opacity:1}.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-active>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-open>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-selected>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-title:hover>.ant-menu-submenu-title:hover>.ant-menu-submenu-arrow:before{background:#fff}.ant-menu-dark .ant-menu-item:hover{background-color:transparent}.ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-selected{background-color:#0052d9}.ant-menu-dark .ant-menu-item-selected{color:#fff;border-right:0}.ant-menu-dark .ant-menu-item-selected:after{border-right:0}.ant-menu-dark .ant-menu-item-selected>a,.ant-menu-dark .ant-menu-item-selected>span>a,.ant-menu-dark .ant-menu-item-selected>a:hover,.ant-menu-dark .ant-menu-item-selected>span>a:hover{color:#fff}.ant-menu-dark .ant-menu-item-selected .anticon{color:#fff}.ant-menu-dark .ant-menu-item-selected .anticon+span{color:#fff}.ant-menu.ant-menu-dark .ant-menu-item-selected,.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected{background-color:#0052d9}.ant-menu-dark .ant-menu-item-disabled,.ant-menu-dark .ant-menu-submenu-disabled,.ant-menu-dark .ant-menu-item-disabled>a,.ant-menu-dark .ant-menu-submenu-disabled>a,.ant-menu-dark .ant-menu-item-disabled>span>a,.ant-menu-dark .ant-menu-submenu-disabled>span>a{color:#ffffff59!important;opacity:.8}.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title{color:#ffffff59!important}.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after{background:rgba(255,255,255,.35)!important}.ant-menu-rtl{direction:rtl}.ant-menu-rtl .ant-menu-item-group-title{text-align:right}.ant-menu-rtl.ant-menu-inline,.ant-menu-rtl.ant-menu-vertical{border-right:none;border-left:1px solid #f0f0f0}.ant-menu-rtl.ant-menu-dark.ant-menu-inline,.ant-menu-rtl.ant-menu-dark.ant-menu-vertical{border-left:none}.ant-menu-rtl.ant-menu-vertical.ant-menu-sub,.ant-menu-rtl.ant-menu-vertical-left.ant-menu-sub,.ant-menu-rtl.ant-menu-vertical-right.ant-menu-sub{transform-origin:top right}.ant-menu-rtl.ant-menu-vertical.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical-left.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical-right.ant-menu-sub>.ant-menu-item,.ant-menu-rtl.ant-menu-vertical.ant-menu-sub>.ant-menu-submenu,.ant-menu-rtl.ant-menu-vertical-left.ant-menu-sub>.ant-menu-submenu,.ant-menu-rtl.ant-menu-vertical-right.ant-menu-sub>.ant-menu-submenu{transform-origin:top right}.ant-menu-rtl .ant-menu-item .anticon,.ant-menu-rtl .ant-menu-submenu-title .anticon{margin-right:auto;margin-left:10px}.ant-menu-rtl .ant-menu-item.ant-menu-item-only-child>.anticon,.ant-menu-rtl .ant-menu-submenu-title.ant-menu-item-only-child>.anticon{margin-left:0}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow,.ant-menu-rtl .ant-menu-submenu-inline>.ant-menu-submenu-title .ant-menu-submenu-arrow{right:auto;left:16px}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:before,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:before{transform:rotate(-45deg) translateY(-2px)}.ant-menu-rtl .ant-menu-submenu-vertical>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-rtl .ant-menu-submenu-vertical-left>.ant-menu-submenu-title .ant-menu-submenu-arrow:after,.ant-menu-rtl .ant-menu-submenu-vertical-right>.ant-menu-submenu-title .ant-menu-submenu-arrow:after{transform:rotate(45deg) translateY(2px)}.ant-menu-rtl.ant-menu-vertical .ant-menu-item:after,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-item:after,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-item:after,.ant-menu-rtl.ant-menu-inline .ant-menu-item:after{right:auto;left:0}.ant-menu-rtl.ant-menu-vertical .ant-menu-item,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-item,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-item,.ant-menu-rtl.ant-menu-inline .ant-menu-item,.ant-menu-rtl.ant-menu-vertical .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-vertical-left .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-vertical-right .ant-menu-submenu-title,.ant-menu-rtl.ant-menu-inline .ant-menu-submenu-title{text-align:right}.ant-menu-rtl.ant-menu-inline .ant-menu-submenu-title{padding-right:0;padding-left:34px}.ant-menu-rtl.ant-menu-vertical .ant-menu-submenu-title{padding-right:16px;padding-left:34px}.ant-menu-rtl.ant-menu-inline-collapsed.ant-menu-vertical .ant-menu-submenu-title{padding:0 32px}.ant-menu-rtl .ant-menu-item-group-list .ant-menu-item,.ant-menu-rtl .ant-menu-item-group-list .ant-menu-submenu-title{padding:0 28px 0 16px}.ant-menu-sub.ant-menu-inline{border:0}.ant-menu-rtl.ant-menu-sub.ant-menu-inline .ant-menu-item-group-title{padding-right:32px;padding-left:0}.ant-message{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:fixed;top:22px;left:0;z-index:1010;width:100%;font-size:14px;pointer-events:none}.ant-message-notice{margin-bottom:-2px;padding:8px 0;text-align:center}.ant-message-notice-content{display:inline-block;overflow:hidden;border-radius:3px;box-shadow:0 6px 12px #0000001a;pointer-events:all}.ant-message-success,.ant-message-error,.ant-message-warning,.ant-message-loading,.ant-message-info{padding:10px 16px}.ant-message-warning{background:#fffbe5;border:1px solid #fbd341}.ant-message-warning .anticon{color:#f9e0c7}.ant-message-success{background:#f2ffe0;border:1px solid #7ad93a}.ant-message-success .anticon{color:#00a870}.ant-message-info{background:#e6f7ff;border:1px solid #8cc6ff}.ant-message-info .anticon{color:#0052d9}.ant-message-error{background:#fff0f0;border:1px solid #fc9c9c}.ant-message-error .anticon{color:#e34d59}.ant-message-loading{background:#f5f7fa;border:1px solid #dadfe6}.ant-message-loading .anticon{color:#0052d9}.ant-message .anticon{position:relative;top:1px;margin-right:6px;font-size:16px}.ant-message-notice.move-up-leave.move-up-leave-active{animation-name:MessageMoveOut;animation-duration:.3s}@keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}.ant-message-rtl,.ant-message-rtl span{direction:rtl}.ant-message-rtl .anticon{margin-right:0;margin-left:8px}.ant-modal{box-sizing:border-box;padding:0 0 24px;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;top:100px;width:auto;margin:0 auto;pointer-events:none}.ant-modal-wrap{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;outline:0;-webkit-overflow-scrolling:touch}.ant-modal-title{margin:0;color:#000a29e6;font-weight:600;font-size:18px;line-height:25px;word-wrap:break-word}.ant-modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:0;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d;pointer-events:auto}.ant-modal-close{position:absolute;top:0;right:0;z-index:10;padding:0;color:#000a2999;font-weight:700;line-height:1;text-decoration:none;background:transparent;border:0;outline:0;cursor:pointer;transition:color .3s}.ant-modal-close-x{display:block;width:56px;height:56px;font-size:16px;font-style:normal;line-height:56px;text-align:center;text-transform:none;text-rendering:auto}.ant-modal-close:focus,.ant-modal-close:hover{color:#000a29bf;text-decoration:none}.ant-modal-header{padding:28px 32px 0;color:#000a29e6;background:#fff;border-radius:3px 3px 0 0}.ant-modal-body{padding:16px 32px 0;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-modal-footer{padding:28px 32px;background:transparent;border-radius:0 0 3px 3px}.ant-modal-footer button+button{margin-bottom:0;margin-left:10px}.ant-modal.zoom-enter,.ant-modal.zoom-appear{transform:none;opacity:0;animation-duration:.3s;user-select:none}.ant-modal-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;height:100%;background-color:#000a2999;filter:alpha(opacity=50)}.ant-modal-mask-hidden{display:none}.ant-modal-open{overflow:hidden}.ant-modal-centered{text-align:center}.ant-modal-centered:before{display:inline-block;width:0;height:100%;vertical-align:middle;content:""}.ant-modal-centered .ant-modal{top:0;display:inline-block;text-align:left;vertical-align:middle}@media (max-width: 767px){.ant-modal{max-width:calc(100vw - 16px);margin:8px auto}.ant-modal-centered .ant-modal{flex:1}}.ant-modal-confirm .ant-modal-header,.ant-modal-confirm .ant-modal-close{display:none}.ant-modal-confirm .ant-modal-body{padding:28px 32px 32px}.ant-modal-confirm-body-wrapper:before{display:table;content:""}.ant-modal-confirm-body-wrapper:after{display:table;clear:both;content:""}.ant-modal-confirm-header{display:flex;align-items:center}.ant-modal-confirm-header .ant-modal-confirm-title{display:block;overflow:hidden;color:#000a29e6;font-weight:600;font-size:16px;line-height:22px}.ant-modal-confirm-header>.anticon{float:left;margin-right:8px;padding:6px;font-size:18px;border-radius:50%}.ant-modal-confirm .ant-modal-confirm-content{margin-top:6px;margin-left:38px;color:#000a29e6;font-size:14px}.ant-modal-confirm .ant-modal-confirm-btns{margin-top:30px;margin-left:38px}.ant-modal-confirm .ant-modal-confirm-btns button+button{margin-bottom:0;margin-left:10px}.ant-modal-confirm-error .ant-modal-confirm-header>.anticon{color:#e34d59;background-color:#fff0f0}.ant-modal-confirm-warning .ant-modal-confirm-header>.anticon,.ant-modal-confirm-confirm .ant-modal-confirm-header>.anticon{color:#f9e0c7;background-color:#fffbe5}.ant-modal-confirm-info .ant-modal-confirm-header>.anticon{color:#0052d9;background-color:#e6f7ff}.ant-modal-confirm-success .ant-modal-confirm-header>.anticon{color:#00a870;background-color:#f2ffe0}.ant-modal-wrap-rtl{direction:rtl}.ant-modal-wrap-rtl .ant-modal-close{right:initial;left:0}.ant-modal-wrap-rtl .ant-modal-footer{text-align:left}.ant-modal-wrap-rtl .ant-modal-footer button+button{margin-right:8px;margin-left:0}.ant-modal-wrap-rtl.ant-modal-centered .ant-modal{text-align:right}.ant-modal-footer{display:flex;flex-direction:row-reverse}.ant-modal-footer button+button{margin-bottom:0;margin-left:0;margin-right:10px}.ant-notification{box-sizing:border-box;margin:0 30px 0 0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:fixed;z-index:1010}.ant-notification-topLeft,.ant-notification-bottomLeft{margin-right:0;margin-left:30px}.ant-notification-topLeft .ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-bottomLeft .ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-topLeft .ant-notification-fade-appear.ant-notification-fade-appear-active,.ant-notification-bottomLeft .ant-notification-fade-appear.ant-notification-fade-appear-active{animation-name:NotificationLeftFadeIn}.ant-notification-close-icon{color:#8592a6;font-size:16px;cursor:pointer}.ant-notification-hook-holder,.ant-notification-notice{position:relative;width:384px;max-width:calc(100vw - 60px);margin-bottom:16px;margin-left:auto;background:#fff;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-notification-topLeft .ant-notification-hook-holder,.ant-notification-topLeft .ant-notification-notice,.ant-notification-bottomLeft .ant-notification-hook-holder,.ant-notification-bottomLeft .ant-notification-notice{margin-right:auto;margin-left:0}.ant-notification-hook-holder-content,.ant-notification-notice-content{overflow:hidden}.ant-notification-hook-holder>.ant-notification-notice{margin-bottom:0;box-shadow:none}.ant-notification-notice{line-height:1.5715;border:1px solid #dadfe6}.ant-notification-notice-message{display:inline-block;margin-bottom:12px;color:#000a29e6;font-weight:600;font-size:16px;line-height:22px}.ant-notification-notice-message-single-line-auto-margin{display:block;width:calc(264px - 100%);max-width:4px;background-color:transparent;pointer-events:none}.ant-notification-notice-message-single-line-auto-margin:before{display:block;content:""}.ant-notification-notice-description{font-size:14px}.ant-notification-notice-closable .ant-notification-notice-message{padding-right:24px}.ant-notification-notice-main{padding:16px 24px}.ant-notification-notice-main-success{border-left:2px solid #00a870}.ant-notification-notice-main-info{border-left:2px solid #0052d9}.ant-notification-notice-main-warning{border-left:2px solid #f9e0c7}.ant-notification-notice-main-error{border-left:2px solid #e34d59}.ant-notification-notice-icon{position:absolute;top:16px;left:-15px;width:30px;height:30px;color:#fff;font-size:16px;line-height:30px;border-radius:30px}.anticon.ant-notification-notice-icon-success{background-color:#00a870}.anticon.ant-notification-notice-icon-info{background-color:#0052d9}.anticon.ant-notification-notice-icon-warning{background-color:#f9e0c7}.anticon.ant-notification-notice-icon-error{background-color:#e34d59}.ant-notification-notice-close{position:absolute;top:14px;right:16px;color:#000a2999;outline:none}.ant-notification-notice-close:hover .anticon{color:#202d40}.ant-notification-notice-btn{display:inline-block;margin-top:20px}.ant-notification .notification-fade-effect{animation-duration:.24s;animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-fill-mode:both}.ant-notification-fade-enter,.ant-notification-fade-appear{opacity:0;animation-duration:.24s;animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-fill-mode:both;animation-play-state:paused}.ant-notification-fade-leave{animation-duration:.24s;animation-timing-function:cubic-bezier(.645,.045,.355,1);animation-fill-mode:both;animation-duration:.2s;animation-play-state:paused}.ant-notification-fade-enter.ant-notification-fade-enter-active,.ant-notification-fade-appear.ant-notification-fade-appear-active{animation-name:NotificationFadeIn;animation-play-state:running}.ant-notification-fade-leave.ant-notification-fade-leave-active{animation-name:NotificationFadeOut;animation-play-state:running}.ant-notification-fade-leave.ant-notification-fade-leave-active .ant-notification-notice-content{animation-name:NotificationContentFadeOut;animation-duration:.2s;animation-play-state:running}@keyframes NotificationFadeIn{0%{left:384px;opacity:0}to{left:0;opacity:1}}@keyframes NotificationLeftFadeIn{0%{right:384px;opacity:0}to{right:0;opacity:1}}@keyframes NotificationFadeOut{0%{max-height:150px;margin-bottom:16px;opacity:1}to{max-height:0;margin-bottom:0;opacity:0}}@keyframes NotificationContentFadeOut{0%{max-height:150px;opacity:1}to{max-height:0;opacity:0}}.ant-notification-rtl{direction:rtl}.ant-notification-rtl .ant-notification-notice-closable .ant-notification-notice-message{padding-right:0;padding-left:24px}.ant-notification-rtl .ant-notification-notice-with-icon .ant-notification-notice-message,.ant-notification-rtl .ant-notification-notice-with-icon .ant-notification-notice-description{margin-right:48px;margin-left:0}.ant-notification-rtl .ant-notification-notice-icon{margin-right:4px;margin-left:0}.ant-notification-rtl .ant-notification-notice-close{right:auto;left:22px}.ant-notification-rtl .ant-notification-notice-btn{float:left}.ant-page-header{box-sizing:border-box;margin:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;padding:16px 24px;background-color:#fff}.ant-page-header-ghost{background-color:inherit}.ant-page-header.has-breadcrumb{padding-top:12px}.ant-page-header.has-footer{padding-bottom:0}.ant-page-header-back{margin-right:16px;font-size:16px;line-height:1}.ant-page-header-back-button{color:#0052d9;text-decoration:none;outline:none;transition:color .3s;color:#000;cursor:pointer}.ant-page-header-back-button:focus,.ant-page-header-back-button:hover{color:#2575e6}.ant-page-header-back-button:active{color:#003eb3}.ant-page-header .ant-divider-vertical{height:14px;margin:0 12px;vertical-align:middle}.ant-breadcrumb+.ant-page-header-heading{margin-top:8px}.ant-page-header-heading{display:flex;justify-content:space-between}.ant-page-header-heading-left{display:flex;align-items:center;margin:4px 0;overflow:hidden}.ant-page-header-heading-title{margin-right:12px;margin-bottom:0;color:#000a29e6;font-weight:600;font-size:20px;line-height:32px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-page-header-heading .ant-avatar{margin-right:12px}.ant-page-header-heading-sub-title{margin-right:12px;color:#000a2999;font-size:14px;line-height:1.5715;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-page-header-heading-extra{margin:4px 0;white-space:nowrap}.ant-page-header-heading-extra>*{margin-left:12px;white-space:unset}.ant-page-header-heading-extra>*:first-child{margin-left:0}.ant-page-header-content{padding-top:12px}.ant-page-header-footer{margin-top:16px}.ant-page-header-footer .ant-tabs-bar{margin-bottom:1px;border-bottom:0}.ant-page-header-footer .ant-tabs-bar .ant-tabs-nav .ant-tabs-tab{padding:8px 0;font-size:16px}.ant-page-header-compact .ant-page-header-heading{flex-wrap:wrap}.ant-page-header-rtl{direction:rtl}.ant-page-header-rtl .ant-page-header-back{float:right;margin-right:0;margin-left:16px}.ant-page-header-rtl .ant-page-header-heading-title,.ant-page-header-rtl .ant-page-header-heading .ant-avatar{margin-right:0;margin-left:12px}.ant-page-header-rtl .ant-page-header-heading-sub-title{float:right;margin-right:0;margin-left:12px}.ant-page-header-rtl .ant-page-header-heading-tags{float:right}.ant-page-header-rtl .ant-page-header-heading-extra{float:left}.ant-page-header-rtl .ant-page-header-heading-extra>*{margin-right:12px;margin-left:0}.ant-page-header-rtl .ant-page-header-heading-extra>*:first-child{margin-right:0}.ant-page-header-rtl .ant-page-header-footer .ant-tabs-bar .ant-tabs-nav{float:right}.ant-pagination{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:flex}.ant-pagination ul,.ant-pagination ol{margin:0;padding:0;list-style:none}.ant-pagination:after{display:block;clear:both;height:0;overflow:hidden;visibility:hidden;content:" "}.ant-pagination-total-text{display:inline-block;height:32px;margin-right:auto;line-height:30px;vertical-align:middle}.ant-pagination-item{display:inline-block;min-width:32px;height:32px;margin-right:8px;font-family:Arial;line-height:30px;text-align:center;vertical-align:middle;list-style:none;background-color:#fff;border-radius:3px;outline:0;cursor:pointer;user-select:none}.ant-pagination-item a{display:block;padding:0 6px;color:#000a29e6;transition:none}.ant-pagination-item a:hover{text-decoration:none}.ant-pagination-item:focus,.ant-pagination-item:hover{background-color:#f5f7fa;border-color:#0052d9;transition:all .3s}.ant-pagination-item:focus a,.ant-pagination-item:hover a{color:#0052d9}.ant-pagination-item-active{font-weight:500;background:#0052d9;border-color:#0052d9}.ant-pagination-item-active a{color:#fff}.ant-pagination-item-active:focus,.ant-pagination-item-active:hover{background:#0052d9;border-color:#2575e6}.ant-pagination-item-active:focus a,.ant-pagination-item-active:hover a{color:#fff}.ant-pagination-jump-prev,.ant-pagination-jump-next{outline:0}.ant-pagination-jump-prev .ant-pagination-item-container,.ant-pagination-jump-next .ant-pagination-item-container{position:relative;width:24px}.ant-pagination-jump-prev .ant-pagination-item-container:focus,.ant-pagination-jump-next .ant-pagination-item-container:focus,.ant-pagination-jump-prev .ant-pagination-item-container:hover,.ant-pagination-jump-next .ant-pagination-item-container:hover{background:#f5f7fa;border-radius:3px}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-link-icon,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-link-icon{color:#0052d9;font-size:12px;letter-spacing:-1px;opacity:0;transition:all .2s}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-link-icon-svg,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-link-icon-svg{top:0;right:0;bottom:0;left:0;margin:auto}.ant-pagination-jump-prev .ant-pagination-item-container .ant-pagination-item-ellipsis,.ant-pagination-jump-next .ant-pagination-item-container .ant-pagination-item-ellipsis{position:absolute;top:0;right:0;bottom:0;left:0;display:block;margin:auto;color:#202d40;font-size:12px;letter-spacing:2px;text-align:center;text-indent:.13em;transform:scale(.6);opacity:1;transition:all .2s}.ant-pagination-jump-prev:focus .ant-pagination-item-link-icon,.ant-pagination-jump-next:focus .ant-pagination-item-link-icon,.ant-pagination-jump-prev:hover .ant-pagination-item-link-icon,.ant-pagination-jump-next:hover .ant-pagination-item-link-icon{opacity:1}.ant-pagination-jump-prev:focus .ant-pagination-item-ellipsis,.ant-pagination-jump-next:focus .ant-pagination-item-ellipsis,.ant-pagination-jump-prev:hover .ant-pagination-item-ellipsis,.ant-pagination-jump-next:hover .ant-pagination-item-ellipsis{opacity:0}.ant-pagination-prev,.ant-pagination-jump-prev,.ant-pagination-jump-next{margin-right:8px}.ant-pagination-prev,.ant-pagination-next,.ant-pagination-jump-prev,.ant-pagination-jump-next{display:inline-block;min-width:32px;height:32px;color:#000a29e6;font-family:Arial;line-height:32px;text-align:center;vertical-align:middle;list-style:none;border-radius:3px;cursor:pointer;transition:all .3s}.ant-pagination-prev,.ant-pagination-next{outline:0}.ant-pagination-prev a,.ant-pagination-next a{color:#000a29e6;user-select:none}.ant-pagination-prev:hover a,.ant-pagination-next:hover a{border-color:#fff}.ant-pagination-prev .ant-pagination-item-link,.ant-pagination-next .ant-pagination-item-link{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:12px;text-align:center;background-color:#fff;border-radius:3px;outline:none;transition:all .3s}.ant-pagination-prev:focus .ant-pagination-item-link,.ant-pagination-next:focus .ant-pagination-item-link,.ant-pagination-prev:hover .ant-pagination-item-link,.ant-pagination-next:hover .ant-pagination-item-link{color:#0052d9;border-color:#0052d9}.ant-pagination-disabled,.ant-pagination-disabled:hover,.ant-pagination-disabled:focus{cursor:not-allowed}.ant-pagination-disabled a,.ant-pagination-disabled:hover a,.ant-pagination-disabled:focus a,.ant-pagination-disabled .ant-pagination-item-link,.ant-pagination-disabled:hover .ant-pagination-item-link,.ant-pagination-disabled:focus .ant-pagination-item-link{color:#00000040;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination-slash{margin:0 10px 0 5px}.ant-pagination-options{display:inline-block;margin-left:16px;vertical-align:middle}@media all and (-ms-high-contrast: none){.ant-pagination-options *::-ms-backdrop,.ant-pagination-options{vertical-align:top}}.ant-pagination-options-size-changer.ant-select{display:inline-block;width:auto}.ant-pagination-options-quick-jumper{display:inline-block;height:32px;margin-left:16px;line-height:32px;vertical-align:top}.ant-pagination-options-quick-jumper input{position:relative;display:inline-block;width:100%;min-width:0;padding:4px 8px;color:#000a29e6;font-size:14px;line-height:1.5715;background-color:#fff;background-image:none;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s;width:50px;margin:0 4px}.ant-pagination-options-quick-jumper input::-moz-placeholder{opacity:1}.ant-pagination-options-quick-jumper input::placeholder{color:#0006}.ant-pagination-options-quick-jumper input:placeholder-shown{text-overflow:ellipsis}.ant-pagination-options-quick-jumper input:hover{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-pagination-options-quick-jumper input:hover{border-right-width:0;border-left-width:1px!important}.ant-pagination-options-quick-jumper input:focus,.ant-pagination-options-quick-jumper input-focused{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-pagination-options-quick-jumper input:focus,.ant-input-rtl .ant-pagination-options-quick-jumper input-focused{border-right-width:0;border-left-width:1px!important}.ant-pagination-options-quick-jumper input-disabled{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-pagination-options-quick-jumper input-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}.ant-pagination-options-quick-jumper input[disabled]{color:#00000040;background-color:#f5f5f5;cursor:not-allowed;opacity:1}.ant-pagination-options-quick-jumper input[disabled]:hover{border-color:#d9d9d9;border-right-width:1px!important}textarea.ant-pagination-options-quick-jumper input{max-width:100%;height:auto;min-height:96px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ant-pagination-options-quick-jumper input-lg{padding:6.5px 8px;font-size:16px}.ant-pagination-options-quick-jumper input-md{padding:3px 7px;font-size:14px}.ant-pagination-options-quick-jumper input-sm{padding:0 8px}.ant-pagination-options-quick-jumper input-rtl{direction:rtl}.ant-pagination-simple .ant-pagination-prev,.ant-pagination-simple .ant-pagination-next{height:24px;line-height:24px;vertical-align:top}.ant-pagination-simple .ant-pagination-prev .ant-pagination-item-link,.ant-pagination-simple .ant-pagination-next .ant-pagination-item-link{height:24px;border:0}.ant-pagination-simple .ant-pagination-prev .ant-pagination-item-link:after,.ant-pagination-simple .ant-pagination-next .ant-pagination-item-link:after{height:24px;line-height:24px}.ant-pagination-simple .ant-pagination-simple-pager{display:inline-block;height:24px;margin-right:8px}.ant-pagination-simple .ant-pagination-simple-pager input{box-sizing:border-box;height:100%;margin-right:8px;padding:0 6px;text-align:center;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;outline:none;transition:border-color .3s}.ant-pagination-simple .ant-pagination-simple-pager input:hover{border-color:#0052d9}.ant-pagination-simple .ant-pagination-simple-pager input:focus{border-color:#2986ff;border-right-width:1px!important;outline:0;-webkit-box-shadow:0 0 4px 0 rgba(0,102,255,.5);box-shadow:0 0 4px #0066ff80}.ant-pagination.mini .ant-pagination-total-text,.ant-pagination.mini .ant-pagination-simple-pager{height:24px;font-size:12px;line-height:24px}.ant-pagination.mini .ant-pagination-item,.ant-pagination.mini .ant-pagination-prev,.ant-pagination.mini .ant-pagination-next{min-width:24px;height:24px;margin:0 10px 0 0;line-height:24px}.ant-pagination.mini .ant-pagination-prev:hover,.ant-pagination.mini .ant-pagination-next:hover{color:#c5cedb;background:#f5f5f5;cursor:not-allowed}.ant-pagination.mini .ant-pagination-next{margin-right:0}.ant-pagination.mini .ant-pagination-prev .ant-pagination-item-link,.ant-pagination.mini .ant-pagination-next .ant-pagination-item-link{background:transparent;border-color:transparent}.ant-pagination.mini .ant-pagination-prev .ant-pagination-item-link:after,.ant-pagination.mini .ant-pagination-next .ant-pagination-item-link:after{height:24px;line-height:24px}.ant-pagination.mini .ant-pagination-jump-prev,.ant-pagination.mini .ant-pagination-jump-next{width:24px;height:24px;margin-right:0;line-height:24px}.ant-pagination.mini .ant-pagination-options{margin-left:12px;font-size:12px}.ant-pagination.mini .ant-pagination-options-size-changer{top:0px;font-size:12px}.ant-pagination.mini .ant-pagination-options-quick-jumper{height:24px;line-height:24px}.ant-pagination.mini .ant-pagination-options-quick-jumper input{padding:0 8px;width:44px}.ant-pagination.ant-pagination-disabled{cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item{background:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item a{color:#00000040;background:transparent;border:none;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-item-active{background:#dbdbdb;border-color:transparent}.ant-pagination.ant-pagination-disabled .ant-pagination-item-active a{color:#fff}.ant-pagination.ant-pagination-disabled .ant-pagination-item-link,.ant-pagination.ant-pagination-disabled .ant-pagination-item-link:hover,.ant-pagination.ant-pagination-disabled .ant-pagination-item-link:focus{color:#000a2999;background:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:focus .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:focus .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:hover .ant-pagination-item-link-icon,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:hover .ant-pagination-item-link-icon{opacity:0}.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:focus .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:focus .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-prev:hover .ant-pagination-item-ellipsis,.ant-pagination.ant-pagination-disabled .ant-pagination-jump-next:hover .ant-pagination-item-ellipsis{opacity:1}@media only screen and (max-width: 992px){.ant-pagination-item-after-jump-prev,.ant-pagination-item-before-jump-next{display:none}}@media only screen and (max-width: 576px){.ant-pagination-options{display:none}}.ant-pagination-rtl{direction:rtl}.ant-pagination-rtl .ant-pagination-total-text,.ant-pagination-rtl .ant-pagination-item,.ant-pagination-rtl .ant-pagination-prev,.ant-pagination-rtl .ant-pagination-jump-prev,.ant-pagination-rtl .ant-pagination-jump-next{margin-right:0;margin-left:8px}.ant-pagination-rtl .ant-pagination-options{margin-right:16px;margin-left:0}.ant-pagination-rtl .ant-pagination-options-size-changer.ant-select,.ant-pagination-rtl.ant-pagination-simple .ant-pagination-simple-pager,.ant-pagination-rtl.ant-pagination-simple .ant-pagination-simple-pager input{margin-right:0;margin-left:8px}.ant-pagination-rtl.ant-pagination.mini .ant-pagination-options{margin-right:2px;margin-left:0}.ant-popover{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:0;left:0;z-index:1030;font-weight:400;white-space:normal;text-align:left;cursor:auto;user-select:text}.ant-popover:after{position:absolute;background:rgba(255,255,255,.01);content:""}.ant-popover-hidden{display:none}.ant-popover-placement-top,.ant-popover-placement-topLeft,.ant-popover-placement-topRight{padding-bottom:10px}.ant-popover-placement-right,.ant-popover-placement-rightTop,.ant-popover-placement-rightBottom{padding-left:10px}.ant-popover-placement-bottom,.ant-popover-placement-bottomLeft,.ant-popover-placement-bottomRight{padding-top:10px}.ant-popover-placement-left,.ant-popover-placement-leftTop,.ant-popover-placement-leftBottom{padding-right:10px}.ant-popover-inner{padding:16px;background-color:#fff;background-clip:padding-box;border:1px solid #e6e9ed;border-radius:3px;box-shadow:0 6px 12px #0000001a}@media screen and (-ms-high-contrast: active),(-ms-high-contrast: none){.ant-popover-inner{box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}}.ant-popover-title{min-width:177px;margin-bottom:8px;color:#000a29e6;font-weight:500}.ant-popover-inner-content{color:#000a29e6}.ant-popover-message{position:relative;padding:4px 0 12px;color:#000a29e6;font-size:14px}.ant-popover-message>.anticon{position:absolute;top:8.0005px;color:#f9e0c7;font-size:14px}.ant-popover-message-title{padding-left:22px}.ant-popover-buttons{margin-bottom:4px;text-align:right}.ant-popover-buttons button{margin-left:8px}.ant-popover-arrow{position:absolute;display:block;width:8.48528137px;height:8.48528137px;background:#fff;transform:rotate(45deg)}.ant-popover-placement-top>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-topLeft>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-topRight>.ant-popover-content>.ant-popover-arrow{bottom:6px;border-right:1px solid #e6e9ed;border-bottom:1px solid #e6e9ed;box-shadow:3px 3px 7px #00000012}.ant-popover-placement-top>.ant-popover-content>.ant-popover-arrow{left:50%;transform:translate(-50%) rotate(45deg)}.ant-popover-placement-topLeft>.ant-popover-content>.ant-popover-arrow{left:16px}.ant-popover-placement-topRight>.ant-popover-content>.ant-popover-arrow{right:16px}.ant-popover-placement-right>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-rightTop>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-rightBottom>.ant-popover-content>.ant-popover-arrow{left:6px;border-bottom:1px solid #e6e9ed;border-left:1px solid #e6e9ed;box-shadow:-3px 3px 7px #00000012}.ant-popover-placement-right>.ant-popover-content>.ant-popover-arrow{top:50%;transform:translateY(-50%) rotate(45deg)}.ant-popover-placement-rightTop>.ant-popover-content>.ant-popover-arrow{top:12px}.ant-popover-placement-rightBottom>.ant-popover-content>.ant-popover-arrow{bottom:12px}.ant-popover-placement-bottom>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-bottomLeft>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-bottomRight>.ant-popover-content>.ant-popover-arrow{top:6px;border-top:1px solid #e6e9ed;border-left:1px solid #e6e9ed;box-shadow:-2px -2px 5px #0000000f}.ant-popover-placement-bottom>.ant-popover-content>.ant-popover-arrow{left:50%;transform:translate(-50%) rotate(45deg)}.ant-popover-placement-bottomLeft>.ant-popover-content>.ant-popover-arrow{left:16px}.ant-popover-placement-bottomRight>.ant-popover-content>.ant-popover-arrow{right:16px}.ant-popover-placement-left>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-leftTop>.ant-popover-content>.ant-popover-arrow,.ant-popover-placement-leftBottom>.ant-popover-content>.ant-popover-arrow{right:6.2px;border-top:1px solid #e6e9ed;border-right:1px solid #e6e9ed;box-shadow:3px -3px 7px #00000012}.ant-popover-placement-left>.ant-popover-content>.ant-popover-arrow{top:50%;transform:translateY(-50%) rotate(45deg)}.ant-popover-placement-leftTop>.ant-popover-content>.ant-popover-arrow{top:12px}.ant-popover-placement-leftBottom>.ant-popover-content>.ant-popover-arrow{bottom:12px}.ant-popover-rtl{direction:rtl;text-align:right}.ant-popover-rtl .ant-popover-message-title{padding-right:22px;padding-left:16px}.ant-popover-rtl .ant-popover-buttons{text-align:left}.ant-popover-rtl .ant-popover-buttons button{margin-right:8px;margin-left:0}.ant-progress{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block}.ant-progress-line{position:relative;width:100%;font-size:14px}.ant-progress-steps{display:inline-block}.ant-progress-steps-outer{display:flex;flex-direction:row;align-items:center}.ant-progress-steps-item{flex-shrink:0;min-width:2px;margin-right:2px;background:#f3f3f3}.ant-progress-small.ant-progress-line,.ant-progress-small.ant-progress-line .ant-progress-text .anticon{font-size:12px}.ant-progress-outer{display:inline-block;width:100%;margin-right:0;padding-right:0}.ant-progress-show-info .ant-progress-outer{margin-right:calc(-2em - 8px);padding-right:calc(2em + 8px)}.ant-progress-inner{position:relative;display:inline-block;width:100%;overflow:hidden;vertical-align:middle;background-color:#f5f5f5;border-radius:100px}.ant-progress-circle-trail{stroke:#f5f5f5}.ant-progress-circle-path{animation:ant-progress-appear .3s}.ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#0052d9}.ant-progress-success-bg,.ant-progress-bg{position:relative;background-color:#0052d9;border-radius:100px;transition:all .4s cubic-bezier(.08,.82,.17,1) 0s}.ant-progress-success-bg{position:absolute;top:0;left:0;background-color:#00a870}.ant-progress-text{display:inline-block;width:2em;margin-left:8px;color:#000a2999;font-size:1em;line-height:1;white-space:nowrap;text-align:left;vertical-align:middle;word-break:normal}.ant-progress-text .anticon{font-size:14px}.ant-progress-status-active .ant-progress-bg:before{position:absolute;top:0;right:0;bottom:0;left:0;background:#fff;border-radius:10px;opacity:0;animation:ant-progress-active 2.4s cubic-bezier(.23,1,.32,1) infinite;content:""}.ant-progress-status-exception .ant-progress-bg{background-color:#e34d59}.ant-progress-status-exception .ant-progress-text{color:#e34d59}.ant-progress-status-exception .ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#e34d59}.ant-progress-status-success .ant-progress-bg{background-color:#00a870}.ant-progress-status-success .ant-progress-text{color:#00a870}.ant-progress-status-success .ant-progress-inner:not(.ant-progress-circle-gradient) .ant-progress-circle-path{stroke:#00a870}.ant-progress-circle .ant-progress-inner{position:relative;line-height:1;background-color:transparent}.ant-progress-circle .ant-progress-text{position:absolute;top:50%;left:50%;width:100%;margin:0;padding:0;color:#000a29e6;font-size:1em;line-height:1;white-space:normal;text-align:center;transform:translate(-50%,-50%)}.ant-progress-circle .ant-progress-text .anticon{font-size:1.16666667em}.ant-progress-circle.ant-progress-status-exception .ant-progress-text{color:#e34d59}.ant-progress-circle.ant-progress-status-success .ant-progress-text{color:#00a870}@keyframes ant-progress-active{0%{width:0;opacity:.1}20%{width:0;opacity:.5}to{width:100%;opacity:0}}.ant-progress-rtl{direction:rtl}.ant-progress-rtl.ant-progress-show-info .ant-progress-outer{margin-right:0;margin-left:calc(-2em - 8px);padding-right:0;padding-left:calc(2em + 8px)}.ant-progress-rtl .ant-progress-success-bg{right:0;left:auto}.ant-progress-rtl.ant-progress-line .ant-progress-text,.ant-progress-rtl.ant-progress-steps .ant-progress-text{margin-right:8px;margin-left:0;text-align:right}.ant-radio-group{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block;line-height:unset}.ant-radio-group .ant-badge-count{z-index:1}.ant-radio-group>.ant-badge:not(:first-child)>.ant-radio-button-wrapper{border-left:none}.ant-radio-wrapper{box-sizing:border-box;margin:0 8px 0 0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;font-size:0;white-space:nowrap;cursor:pointer}.ant-radio{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;top:0px;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-radio-wrapper:hover .ant-radio,.ant-radio:hover .ant-radio-inner,.ant-radio-input:focus+.ant-radio-inner{border-color:#0052d9}.ant-radio-input:focus+.ant-radio-inner{box-shadow:0 0 0 3px #0052d914}.ant-radio-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #0052d9;border-radius:50%;visibility:hidden;animation:antRadioEffect .36s ease-in-out;animation-fill-mode:both;content:""}.ant-radio:hover:after,.ant-radio-wrapper:hover .ant-radio:after{visibility:visible}.ant-radio-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border-color:#d9d9d9;border-style:solid;border-width:1px;border-radius:100px;transition:all .3s}.ant-radio-inner:after{position:absolute;top:3px;left:3px;display:table;width:8px;height:8px;background-color:#0052d9;border-top:0;border-left:0;border-radius:8px;transform:scale(0);opacity:0;transition:all .3s cubic-bezier(.78,.14,.15,.86);content:" "}.ant-radio-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;cursor:pointer;opacity:0}.ant-radio-checked .ant-radio-inner{border-color:#0052d9}.ant-radio-checked .ant-radio-inner:after{transform:scale(1);opacity:1;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-radio-disabled{cursor:not-allowed}.ant-radio-disabled .ant-radio-inner{background-color:#f5f5f5;border-color:#d9d9d9!important;cursor:not-allowed}.ant-radio-disabled .ant-radio-inner:after{background-color:#0003}.ant-radio-disabled .ant-radio-input{cursor:not-allowed}.ant-radio-disabled+span{color:#adbacc;cursor:not-allowed}span.ant-radio+*{padding-right:8px;padding-left:8px;font-size:14px;vertical-align:middle}.ant-radio-button-wrapper{position:relative;display:inline-block;height:32px;margin:0;padding:0 15px;color:#000a29e6;line-height:30px;background:#fff;border:1px solid #d9d9d9;border-top-width:1.02px;border-left-width:0;cursor:pointer;transition:color .3s,background .3s,border-color .3s,box-shadow .3s}.ant-radio-button-wrapper a{color:#000a29e6}.ant-radio-button-wrapper>.ant-radio-button{display:block;width:0;height:0;margin-left:0}.ant-radio-group-large .ant-radio-button-wrapper{height:40px;font-size:16px;line-height:38px}.ant-radio-group-small .ant-radio-button-wrapper{height:24px;padding:0 7px;line-height:22px}.ant-radio-button-wrapper:not(:first-child):before{position:absolute;top:-1px;left:-1px;display:block;box-sizing:content-box;width:1px;height:100%;padding:1px 0;background-color:#d9d9d9;transition:background-color .3s;content:""}.ant-radio-button-wrapper:first-child{border-left:1px solid #d9d9d9;border-radius:3px 0 0 3px}.ant-radio-button-wrapper:last-child{border-radius:0 3px 3px 0}.ant-radio-button-wrapper:first-child:last-child{border-radius:3px}.ant-radio-button-wrapper:hover{position:relative;color:#0052d9}.ant-radio-button-wrapper:focus-within{box-shadow:0 0 0 3px #0052d914}.ant-radio-button-wrapper .ant-radio-inner,.ant-radio-button-wrapper input[type=checkbox],.ant-radio-button-wrapper input[type=radio]{width:0;height:0;opacity:0;pointer-events:none}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){z-index:1;color:#0052d9;background:#fff;border-color:#0052d9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):before{background-color:#0052d9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):first-child{border-color:#0052d9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#2575e6;border-color:#2575e6}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover:before{background-color:#2575e6}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#003eb3;border-color:#003eb3}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active:before{background-color:#003eb3}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{box-shadow:0 0 0 3px #0052d914}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){color:#fff;background:#0052d9;border-color:#0052d9}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#fff;background:#2575e6;border-color:#2575e6}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#fff;background:#003eb3;border-color:#003eb3}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{box-shadow:0 0 0 3px #0052d914}.ant-radio-button-wrapper-disabled{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-radio-button-wrapper-disabled:first-child,.ant-radio-button-wrapper-disabled:hover{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9}.ant-radio-button-wrapper-disabled:first-child{border-left-color:#d9d9d9}.ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked{color:#fff;background-color:#e6e6e6;border-color:#d9d9d9;box-shadow:none}@keyframes antRadioEffect{0%{transform:scale(1);opacity:.5}to{transform:scale(1.6);opacity:0}}@supports (-moz-appearance: meterbar) and (background-blend-mode: difference,normal){.ant-radio{vertical-align:text-bottom}}.ant-radio-group.ant-radio-group-rtl{direction:rtl}.ant-radio-wrapper.ant-radio-wrapper-rtl{margin-right:0;margin-left:8px;direction:rtl}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl{border-right-width:0;border-left-width:1px}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:not(:first-child):before{right:-1px;left:0}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:first-child{border-right:1px solid #d9d9d9;border-radius:0 3px 3px 0}.ant-radio-button-wrapper-checked:not([class*=" ant-radio-button-wrapper-disabled"]).ant-radio-button-wrapper:first-child{border-right-color:#2575e6}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:last-child{border-radius:3px 0 0 3px}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper-disabled:first-child{border-right-color:#d9d9d9}.ant-rate{box-sizing:border-box;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:"tnum";display:inline-block;margin:0;padding:0;color:#ce9c09;font-size:20px;line-height:unset;list-style:none;outline:none}.ant-rate-disabled .ant-rate-star{cursor:default}.ant-rate-disabled .ant-rate-star:hover{transform:scale(1)}.ant-rate-star{position:relative;display:inline-block;margin:0;padding:0;color:inherit;cursor:pointer;transition:all .3s}.ant-rate-star:not(:last-child){margin-right:8px}.ant-rate-star>div:focus{outline:0}.ant-rate-star>div:hover,.ant-rate-star>div:focus{transform:scale(1.1)}.ant-rate-star-first,.ant-rate-star-second{color:#f0f0f0;transition:all .3s;user-select:none}.ant-rate-star-first .anticon,.ant-rate-star-second .anticon{vertical-align:middle}.ant-rate-star-first{position:absolute;top:0;left:0;width:50%;height:100%;overflow:hidden;opacity:0}.ant-rate-star-half .ant-rate-star-first,.ant-rate-star-half .ant-rate-star-second{opacity:1}.ant-rate-star-half .ant-rate-star-first,.ant-rate-star-full .ant-rate-star-second{color:inherit}.ant-rate-text{display:inline-block;margin:0 8px;font-size:14px}.ant-rate-rtl{direction:rtl}.ant-rate-rtl .ant-rate-star:not(:last-child){margin-right:0;margin-left:8px}.ant-rate-rtl .ant-rate-star-first{right:0;left:auto}.ant-result{padding:48px 32px}.ant-result-success .ant-result-icon>.anticon{color:#00a870}.ant-result-error .ant-result-icon>.anticon{color:#e34d59}.ant-result-info .ant-result-icon>.anticon{color:#0052d9}.ant-result-warning .ant-result-icon>.anticon{color:#f9e0c7}.ant-result-image{width:250px;height:295px;margin:auto}.ant-result-icon{margin-bottom:24px;text-align:center}.ant-result-icon>.anticon{font-size:72px}.ant-result-title{color:#000a29e6;font-size:24px;line-height:1.8;text-align:center}.ant-result-subtitle{color:#000a2999;font-size:14px;line-height:1.6;text-align:center}.ant-result-extra{margin:32px 0 0;text-align:center}.ant-result-extra>*{margin-right:8px}.ant-result-extra>*:last-child{margin-right:0}.ant-result-content{margin-top:24px;padding:24px 40px;background-color:#f1f2f5}.ant-result-rtl{direction:rtl}.ant-result-rtl .ant-result-extra>*{margin-right:0;margin-left:8px}.ant-result-rtl .ant-result-extra>*:last-child{margin-left:0}.ant-select-single .ant-select-selector{display:flex}.ant-select-single .ant-select-selector .ant-select-selection-search{position:absolute;top:0;right:8px;bottom:0;left:8px}.ant-select-single .ant-select-selector .ant-select-selection-search-input{width:100%}.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{padding:0;line-height:30px;transition:all .3s;pointer-events:none}@supports (-moz-appearance: meterbar){.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{line-height:30px}}.ant-select-single .ant-select-selector:after,.ant-select-single .ant-select-selector .ant-select-selection-item:after,.ant-select-single .ant-select-selector .ant-select-selection-placeholder:after{display:inline-block;width:0;visibility:hidden;content:"\a0"}.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:22px}.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:18px}.ant-select-single.ant-select-open .ant-select-selection-item{color:#0006}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s cubic-bezier(.645,.045,.355,1);width:100%;height:32px;padding:0 8px}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{cursor:text}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-select-focused.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{border-right-width:0;border-left-width:1px!important}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:not-allowed}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{height:30px}.ant-select-single.ant-select-customize-input .ant-select-selector:after{display:none}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-search{position:static;width:100%}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder{position:absolute;right:0;left:0;padding:0 8px}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder:after{display:none}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{height:40px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:38px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:38px}.ant-select-single.ant-select-md:not(.ant-select-customize-input) .ant-select-selector{height:30px}.ant-select-single.ant-select-md:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-md:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:28px}.ant-select-single.ant-select-md:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:28px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{height:24px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:22px}.ant-select-single.ant-select-sm .ant-select-arrow{right:7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selection-search{right:8px;left:8px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{padding:0 8px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:29px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:21px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{padding:0 8px}.ant-select-multiple .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;transition:all .3s cubic-bezier(.645,.045,.355,1);display:flex;flex-wrap:wrap;align-items:center;padding:1px 4px}.ant-select-multiple .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-multiple .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-multiple .ant-select-selector{border-color:#0052d9;border-right-width:1px!important;outline:0;box-shadow:0 0 0 2px #0052d933}.ant-input-rtl .ant-select-focused.ant-select-multiple .ant-select-selector{border-right-width:0;border-left-width:1px!important}.ant-select-disabled.ant-select-multiple .ant-select-selector{color:#00000040;background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-multiple .ant-select-selector input{cursor:not-allowed}.ant-select-multiple .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-multiple .ant-select-selector:after{display:inline-block;width:0;margin:2px 0;line-height:24px;content:"\a0"}.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:20px}.ant-select-multiple .ant-select-selection-item{position:relative;display:flex;flex:none;box-sizing:border-box;max-width:100%;height:24px;margin-top:2px;margin-right:4px;margin-bottom:2px;padding:0 4px 0 6px;line-height:22px;background:#f5f5f5;border:1px solid #f0f0f0;border-radius:3px;cursor:default;transition:font-size .3s,line-height .3s,height .3s;user-select:none}.ant-select-multiple .ant-select-selection-item-content{display:inline-block;margin-right:4px;overflow:hidden;font-size:12px;white-space:nowrap;text-overflow:ellipsis}.ant-select-multiple .ant-select-selection-item-remove{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#000a2999;font-weight:700;font-size:12px;line-height:inherit;cursor:pointer;display:inline-block;font-size:10px}.ant-select-multiple .ant-select-selection-item-remove>*{line-height:1}.ant-select-multiple .ant-select-selection-item-remove svg{display:inline-block}.ant-select-multiple .ant-select-selection-item-remove:before{display:none}.ant-select-multiple .ant-select-selection-item-remove .ant-select-multiple .ant-select-selection-item-remove-icon{display:block}.ant-select-multiple .ant-select-selection-item-remove>.anticon{vertical-align:-.2em}.ant-select-multiple .ant-select-selection-item-remove:hover{color:#000a29bf}.ant-select-multiple .ant-select-selection-search{position:relative;margin-left:.5px}.ant-select-multiple .ant-select-selection-search-input,.ant-select-multiple .ant-select-selection-search-mirror{font-family:PingFang SC,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5715;transition:all .3s}.ant-select-multiple .ant-select-selection-search-input{width:100%;min-width:3px}.ant-select-multiple .ant-select-selection-search-mirror{position:absolute;top:0;left:0;z-index:999;white-space:nowrap;visibility:hidden}.ant-select-multiple .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:2.5px}.ant-select-multiple .ant-select-selection-placeholder{position:absolute;top:50%;right:8px;left:8px;transform:translateY(-50%);transition:all .3s}.ant-select-multiple.ant-select-lg .ant-select-selector:after{line-height:32px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:30px}.ant-select-multiple.ant-select-lg .ant-select-selection-search{height:33px;line-height:33px}.ant-select-multiple.ant-select-lg .ant-select-selection-search-input,.ant-select-multiple.ant-select-lg .ant-select-selection-search-mirror{height:32px;line-height:30px}.ant-select-multiple.ant-select-md .ant-select-selector:after{line-height:22px}.ant-select-multiple.ant-select-md .ant-select-selection-item{height:22px;line-height:20px}.ant-select-multiple.ant-select-md .ant-select-selection-search{height:23px;line-height:23px}.ant-select-multiple.ant-select-md .ant-select-selection-search-input,.ant-select-multiple.ant-select-md .ant-select-selection-search-mirror{height:22px;line-height:20px}.ant-select-multiple.ant-select-sm .ant-select-selector:after{line-height:16px}.ant-select-multiple.ant-select-sm .ant-select-selection-item{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-search{height:17px;line-height:17px}.ant-select-multiple.ant-select-sm .ant-select-selection-search-input,.ant-select-multiple.ant-select-sm .ant-select-selection-search-mirror{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{left:8px}.ant-select-multiple.ant-select-sm .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:3px}.ant-select-multiple.ant-select-sm .ant-select-selector{padding-left:4px}.ant-select-multiple.ant-select-sm .ant-select-selection-item{height:16px;margin:0 4px 0 0;line-height:14px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:32px}.ant-select-multiple.ant-select-disabled .ant-select-selection-item{border:1px solid #dadfe6}.ant-select-disabled .ant-select-selection-item-remove{display:none}.ant-select{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;cursor:pointer}.ant-select:not(.ant-select-disabled):hover .ant-select-selector{border-color:#2575e6;border-right-width:1px!important}.ant-input-rtl .ant-select:not(.ant-select-disabled):hover .ant-select-selector{border-right-width:0;border-left-width:1px!important}.ant-select-selection-item{flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media all and (-ms-high-contrast: none){.ant-select-selection-item *::-ms-backdrop,.ant-select-selection-item{flex:auto}}.ant-select-selection-placeholder{flex:1;overflow:hidden;color:#0006;white-space:nowrap;text-overflow:ellipsis}@media all and (-ms-high-contrast: none){.ant-select-selection-placeholder *::-ms-backdrop,.ant-select-selection-placeholder{flex:auto}}.ant-select-arrow{display:inline-block;color:inherit;font-style:normal;line-height:0;text-transform:none;vertical-align:-.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:50%;right:7px;width:16px;height:16px;margin-top:-8px;color:#8592a6;font-size:16px;line-height:1;text-align:center;pointer-events:none}.ant-select-arrow>*{line-height:1}.ant-select-arrow svg{display:inline-block}.ant-select-arrow:before{display:none}.ant-select-arrow .ant-select-arrow-icon{display:block}.ant-select-arrow .anticon{vertical-align:top;transition:transform .3s}.ant-select-arrow .anticon>svg{vertical-align:top}.ant-select-arrow .anticon:not(.ant-select-suffix){pointer-events:auto}.ant-select-arrow-loading{color:#06f}.ant-select-disabled .ant-select-arrow{color:#c5cedb;cursor:not-allowed}.ant-select-clear{position:absolute;top:50%;right:7px;z-index:1;display:inline-block;width:16px;height:16px;margin-top:-8px;color:#00000040;font-size:16px;font-style:normal;line-height:1;text-align:center;text-transform:none;background:#fff;cursor:pointer;opacity:0;transition:color .3s ease,opacity .15s ease;text-rendering:auto}.ant-select-clear:before{display:block}.ant-select-clear:hover{color:#000a2999}.ant-select:hover .ant-select-clear{opacity:1}.ant-select-dropdown{margin:0;color:#000a29e6;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:-9999px;left:-9999px;z-index:1050;box-sizing:border-box;padding:4px 1px;overflow:hidden;font-size:14px;font-variant:initial;background-color:#fff;border-radius:3px;outline:none;box-shadow:0 2px 4px #0000001a,0 0 0 1px #dadfe6 inset}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-bottomLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-bottomLeft{animation-name:antSlideUpIn}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-topLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-topLeft{animation-name:antSlideDownIn}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-bottomLeft{animation-name:antSlideUpOut}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-topLeft{animation-name:antSlideDownOut}.ant-select-dropdown-hidden{display:none}.ant-select-item-empty{position:relative;display:block;min-height:32px;color:#000a29e6;font-weight:400;font-size:14px;line-height:22px;min-height:unset;padding:3px 16px;color:#c5cedb}.ant-select-item{position:relative;display:block;min-height:32px;padding:5px 16px;color:#000a29e6;font-weight:400;font-size:14px;line-height:22px;cursor:pointer;transition:background .3s ease}.ant-select-item-group{padding-left:12px;color:#8592a6;font-size:12px;cursor:default}.ant-select-item-option{display:flex}.ant-select-item-option-content{flex:auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-item-option-state{flex:none}.ant-select-item-option-active:not(.ant-select-item-option-disabled){background-color:#f3f3f3}.ant-select-item-option-selected:not(.ant-select-item-option-disabled){color:#000a29e6;font-weight:600;background-color:#e0ebff}.ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state{color:#0052d9}.ant-select-item-option-disabled{color:#c5cedb;cursor:not-allowed}.ant-select-item-option-grouped{padding-left:16px}.ant-select-lg{font-size:16px}.ant-select-borderless .ant-select-selector{height:unset!important;background-color:transparent!important;border-color:transparent!important;box-shadow:none!important}.ant-select-borderless .ant-select-selector .ant-select-selection-item{padding-right:22px;line-height:unset}.ant-select-borderless .ant-select-arrow{margin-left:4px;transition:all .3s}.ant-select-borderless:not(.ant-select-disabled):hover{color:#06f}.ant-select-borderless:not(.ant-select-disabled):hover .ant-select-arrow{color:#06f}.ant-select-borderless.ant-select-open .ant-select-selection-item,.ant-select-borderless.ant-select-open .ant-select-arrow{color:#06f}.ant-select-rtl{direction:rtl}.ant-select-rtl .ant-select-arrow,.ant-select-rtl .ant-select-clear{right:initial;left:7px}.ant-select-dropdown-rtl{direction:rtl}.ant-select-dropdown-rtl .ant-select-item-option-grouped{padding-right:16px;padding-left:8px}.ant-select-rtl.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:4px;padding-left:20px}.ant-select-rtl.ant-select-multiple .ant-select-selection-item{margin-right:0;margin-left:4px;padding:0 8px 0 4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-item-content{margin-right:0;margin-left:4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-search{margin-right:.5px;margin-left:4px}.ant-select-rtl.ant-select-multiple .ant-select-selection-search-mirror{right:0;left:auto}.ant-select-rtl.ant-select-multiple .ant-select-selection-placeholder{right:8px;left:auto}.ant-select-rtl.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{right:8px}.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-placeholder{right:0;left:9px;text-align:right}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:8px;left:22px}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:18px}.ant-select-rtl.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{padding:0 8px}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:0}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:21px}.ant-skeleton{display:table;width:100%}.ant-skeleton-header{display:table-cell;padding-right:16px;vertical-align:top}.ant-skeleton-header .ant-skeleton-avatar{display:inline-block;vertical-align:top;background:#f2f2f2;width:32px;height:32px;line-height:32px}.ant-skeleton-header .ant-skeleton-avatar.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-header .ant-skeleton-avatar-lg{width:40px;height:40px;line-height:40px}.ant-skeleton-header .ant-skeleton-avatar-lg.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-header .ant-skeleton-avatar-sm{width:24px;height:24px;line-height:24px}.ant-skeleton-header .ant-skeleton-avatar-sm.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-content{display:table-cell;width:100%;vertical-align:top}.ant-skeleton-content .ant-skeleton-title{width:100%;height:16px;margin-top:16px;background:#f2f2f2}.ant-skeleton-content .ant-skeleton-title+.ant-skeleton-paragraph{margin-top:24px}.ant-skeleton-content .ant-skeleton-paragraph{padding:0}.ant-skeleton-content .ant-skeleton-paragraph>li{width:100%;height:16px;list-style:none;background:#f2f2f2}.ant-skeleton-content .ant-skeleton-paragraph>li:last-child:not(:first-child):not(:nth-child(2)){width:61%}.ant-skeleton-content .ant-skeleton-paragraph>li+li{margin-top:16px}.ant-skeleton-with-avatar .ant-skeleton-content .ant-skeleton-title{margin-top:12px}.ant-skeleton-with-avatar .ant-skeleton-content .ant-skeleton-title+.ant-skeleton-paragraph{margin-top:28px}.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-title,.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-paragraph>li{background:linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);background-size:400% 100%;animation:ant-skeleton-loading 1.4s ease infinite}.ant-skeleton.ant-skeleton-active .ant-skeleton-avatar,.ant-skeleton.ant-skeleton-active .ant-skeleton-button,.ant-skeleton.ant-skeleton-active .ant-skeleton-input{background:linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);background-size:400% 100%;animation:ant-skeleton-loading 1.4s ease infinite}.ant-skeleton-element{display:inline-block}.ant-skeleton-element .ant-skeleton-button{display:inline-block;vertical-align:top;background:#f2f2f2;border-radius:3px;width:64px;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-button.ant-skeleton-button-circle{width:32px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button.ant-skeleton-button-round{border-radius:32px}.ant-skeleton-element .ant-skeleton-button-lg{width:80px;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-button-lg.ant-skeleton-button-circle{width:40px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button-lg.ant-skeleton-button-round{border-radius:40px}.ant-skeleton-element .ant-skeleton-button-sm{width:48px;height:24px;line-height:24px}.ant-skeleton-element .ant-skeleton-button-sm.ant-skeleton-button-circle{width:24px;border-radius:50%}.ant-skeleton-element .ant-skeleton-button-sm.ant-skeleton-button-round{border-radius:24px}.ant-skeleton-element .ant-skeleton-avatar{display:inline-block;vertical-align:top;background:#f2f2f2;width:32px;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-avatar.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-avatar-lg{width:40px;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-avatar-lg.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-avatar-sm{width:24px;height:24px;line-height:24px}.ant-skeleton-element .ant-skeleton-avatar-sm.ant-skeleton-avatar-circle{border-radius:50%}.ant-skeleton-element .ant-skeleton-input{display:inline-block;vertical-align:top;background:#f2f2f2;width:100%;height:32px;line-height:32px}.ant-skeleton-element .ant-skeleton-input-lg{width:100%;height:40px;line-height:40px}.ant-skeleton-element .ant-skeleton-input-sm{width:100%;height:24px;line-height:24px}@keyframes ant-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.ant-skeleton-rtl{direction:rtl}.ant-skeleton-rtl .ant-skeleton-header{padding-right:0;padding-left:16px}.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-title,.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-content .ant-skeleton-paragraph>li{animation-name:ant-skeleton-loading-rtl}.ant-skeleton-rtl.ant-skeleton.ant-skeleton-active .ant-skeleton-avatar{animation-name:ant-skeleton-loading-rtl}@keyframes ant-skeleton-loading-rtl{0%{background-position:0% 50%}to{background-position:100% 50%}}.ant-slider{box-sizing:border-box;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;height:12px;margin:10px 6px;padding:4px 0;cursor:pointer;touch-action:none}.ant-slider-vertical{width:12px;height:100%;margin:6px 10px;padding:0 4px}.ant-slider-vertical .ant-slider-rail{width:4px;height:100%}.ant-slider-vertical .ant-slider-track{width:4px}.ant-slider-vertical .ant-slider-handle{margin-top:-6px;margin-left:-5px}.ant-slider-vertical .ant-slider-mark{top:0;left:12px;width:18px;height:100%}.ant-slider-vertical .ant-slider-mark-text{left:4px;white-space:nowrap}.ant-slider-vertical .ant-slider-step{width:4px;height:100%}.ant-slider-vertical .ant-slider-dot{top:auto;left:2px;margin-bottom:-4px}.ant-slider-tooltip .ant-tooltip-inner{min-width:unset}.ant-slider-rtl.ant-slider-vertical .ant-slider-handle{margin-right:-5px;margin-left:0}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark{right:12px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark-text{right:4px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-dot{right:2px;left:auto}.ant-slider-with-marks{margin-bottom:28px}.ant-slider-rail{position:absolute;width:100%;height:4px;background-color:#f5f5f5;border-radius:3px;transition:background-color .3s}.ant-slider-track{position:absolute;height:4px;background-color:#7abaff;border-radius:3px;transition:background-color .3s}.ant-slider-handle{position:absolute;width:14px;height:14px;margin-top:-5px;background-color:#fff;border:solid 2px #7abaff;border-radius:50%;box-shadow:0;cursor:pointer;transition:border-color .3s,box-shadow .6s,transform .3s cubic-bezier(.18,.89,.32,1.28)}.ant-slider-handle-dragging.ant-slider-handle-dragging.ant-slider-handle-dragging{border-color:#3375e1;box-shadow:0 0 0 5px #0052d91f}.ant-slider-handle:focus{border-color:#3375e1;outline:none;box-shadow:0 0 0 5px #0052d91f}.ant-slider-handle.ant-tooltip-open{border-color:#0052d9}.ant-slider:hover .ant-slider-rail{background-color:#e1e1e1}.ant-slider:hover .ant-slider-track{background-color:#4e98f2}.ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open){border-color:#4e98f2}.ant-slider-mark{position:absolute;top:14px;left:0;width:100%;font-size:14px}.ant-slider-mark-text{position:absolute;display:inline-block;color:#000a2999;text-align:center;word-break:keep-all;cursor:pointer;user-select:none}.ant-slider-mark-text-active{color:#000a29e6}.ant-slider-step{position:absolute;width:100%;height:4px;background:transparent}.ant-slider-dot{position:absolute;top:-2px;width:8px;height:8px;margin-left:-4px;background-color:#fff;border:2px solid #f0f0f0;border-radius:50%;cursor:pointer}.ant-slider-dot:first-child{margin-left:-4px}.ant-slider-dot:last-child{margin-left:-4px}.ant-slider-dot-active{border-color:#80a9ec}.ant-slider-disabled{cursor:not-allowed}.ant-slider-disabled .ant-slider-track{background-color:#00000040!important}.ant-slider-disabled .ant-slider-handle,.ant-slider-disabled .ant-slider-dot{background-color:#fff;border-color:#00000040!important;box-shadow:none;cursor:not-allowed}.ant-slider-disabled .ant-slider-mark-text,.ant-slider-disabled .ant-slider-dot{cursor:not-allowed!important}.ant-slider-rtl{direction:rtl}.ant-slider-rtl .ant-slider-mark{right:0;left:auto}.ant-slider-rtl .ant-slider-dot,.ant-slider-rtl .ant-slider-dot:first-child{margin-right:-4px;margin-left:0}.ant-slider-rtl .ant-slider-dot:last-child{margin-right:-4px;margin-left:0}.ant-space{display:inline-flex}.ant-space-vertical{flex-direction:column}.ant-space-align-center{align-items:center}.ant-space-align-start{align-items:flex-start}.ant-space-align-end{align-items:flex-end}.ant-space-align-baseline{align-items:baseline}.ant-space-rtl{direction:rtl}.ant-spin{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;display:none;color:#0052d9;text-align:center;vertical-align:middle;opacity:0;transition:transform .3s cubic-bezier(.78,.14,.15,.86)}.ant-spin-spinning{position:static;display:inline-block;opacity:1}.ant-spin-nested-loading{position:relative}.ant-spin-nested-loading>div>.ant-spin{position:absolute;top:0;left:0;z-index:4;display:block;width:100%;height:100%;max-height:400px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-dot{position:absolute;top:50%;left:50%;margin:-10px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-text{position:absolute;top:50%;width:100%;padding-top:5px;text-shadow:0 1px 2px #fff}.ant-spin-nested-loading>div>.ant-spin.ant-spin-show-text .ant-spin-dot{margin-top:-20px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-dot{margin:-7px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-text{padding-top:2px}.ant-spin-nested-loading>div>.ant-spin-sm.ant-spin-show-text .ant-spin-dot{margin-top:-17px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-dot{margin:-16px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-text{padding-top:11px}.ant-spin-nested-loading>div>.ant-spin-lg.ant-spin-show-text .ant-spin-dot{margin-top:-26px}.ant-spin-container{position:relative;transition:opacity .3s}.ant-spin-container:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;display:none \ ;width:100%;height:100%;background:#fff;opacity:0;transition:all .3s;content:"";pointer-events:none}.ant-spin-blur{clear:both;overflow:hidden;opacity:.5;user-select:none;pointer-events:none}.ant-spin-blur:after{opacity:.4;pointer-events:auto}.ant-spin-tip{color:#000a2999}.ant-spin-dot{position:relative;display:inline-block;font-size:20px;width:1em;height:1em}.ant-spin-dot-item{position:absolute;display:block;width:9px;height:9px;background-color:#0052d9;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.ant-spin-dot-item:nth-child(1){top:0;left:0}.ant-spin-dot-item:nth-child(2){top:0;right:0;animation-delay:.4s}.ant-spin-dot-item:nth-child(3){right:0;bottom:0;animation-delay:.8s}.ant-spin-dot-item:nth-child(4){bottom:0;left:0;animation-delay:1.2s}.ant-spin-dot-spin{transform:rotate(45deg);animation:antRotate 1.2s infinite linear}.ant-spin-sm .ant-spin-dot{font-size:14px}.ant-spin-sm .ant-spin-dot i{width:6px;height:6px}.ant-spin-lg .ant-spin-dot{font-size:32px}.ant-spin-lg .ant-spin-dot i{width:14px;height:14px}.ant-spin.ant-spin-show-text .ant-spin-text{display:block}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.ant-spin-blur{background:#fff;opacity:.5}}@keyframes antSpinMove{to{opacity:1}}@keyframes antRotate{to{transform:rotate(405deg)}}.ant-spin-rtl{direction:rtl}.ant-spin-rtl .ant-spin-dot-spin{transform:rotate(-45deg);animation-name:antRotateRtl}@keyframes antRotateRtl{to{transform:rotate(-405deg)}}.ant-statistic{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum"}.ant-statistic-title{margin-bottom:4px;color:#000a2999;font-size:14px}.ant-statistic-content{color:#000a29e6;font-size:24px;font-family:PingFang SC,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.ant-statistic-content-value{display:inline-block;direction:ltr}.ant-statistic-content-value-decimal{font-size:16px}.ant-statistic-content-prefix,.ant-statistic-content-suffix{display:inline-block}.ant-statistic-content-prefix{margin-right:4px}.ant-statistic-content-suffix{margin-left:4px;font-size:16px}.ant-statistic-rtl{direction:rtl}.ant-statistic-rtl .ant-statistic-content-prefix{margin-right:0;margin-left:4px}.ant-statistic-rtl .ant-statistic-content-suffix{margin-right:4px;margin-left:0}.ant-steps{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:flex;width:100%;font-size:0}.ant-steps-item{position:relative;display:inline-block;flex:1;overflow:hidden;vertical-align:top}.ant-steps-item-container{outline:none}.ant-steps-item:last-child{flex:none}.ant-steps-item:last-child>.ant-steps-item-container>.ant-steps-item-tail,.ant-steps-item:last-child>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-item-icon,.ant-steps-item-content{display:inline-block;vertical-align:top}.ant-steps-item-icon{width:32px;height:32px;margin:0 8px 0 0;font-size:16px;font-family:PingFang SC,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:32px;text-align:center;border:1px solid rgba(0,0,0,.25);border-radius:32px;transition:background-color .3s,border-color .3s}.ant-steps-item-icon>.ant-steps-icon{position:relative;top:-1px;color:#0052d9;line-height:1}.ant-steps-item-tail{position:absolute;top:12px;left:0;width:100%;padding:0 10px}.ant-steps-item-tail:after{display:inline-block;width:100%;height:1px;background:#f0f0f0;border-radius:1px;transition:background .3s;content:""}.ant-steps-item-title{position:relative;display:inline-block;padding-right:16px;color:#000a29e6;font-size:16px;line-height:32px}.ant-steps-item-title:after{position:absolute;top:16px;left:100%;display:block;width:9999px;height:1px;background:#f0f0f0;content:""}.ant-steps-item-subtitle{display:inline;margin-left:8px;color:#000a2999;font-weight:400;font-size:14px}.ant-steps-item-description{color:#000a2999;font-size:14px}.ant-steps-item-wait .ant-steps-item-icon{background-color:#fff;border-color:#00000040}.ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon{color:#00000040}.ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:rgba(0,0,0,.25)}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#000a2999}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#000a2999}.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item-process .ant-steps-item-icon{background-color:#fff;border-color:#0052d9}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#0052d9}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#0052d9}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#000a29e6}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#000a29e6}.ant-steps-item-process>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item-process .ant-steps-item-icon{background:#0052d9}.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#fff}.ant-steps-item-process .ant-steps-item-title{font-weight:500}.ant-steps-item-finish .ant-steps-item-icon{background-color:#fff;border-color:#0052d9}.ant-steps-item-finish .ant-steps-item-icon>.ant-steps-icon{color:#0052d9}.ant-steps-item-finish .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#0052d9}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#000a29e6}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#0052d9}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#000a2999}.ant-steps-item-finish>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#0052d9}.ant-steps-item-error .ant-steps-item-icon{background-color:#fff;border-color:#e34d59}.ant-steps-item-error .ant-steps-item-icon>.ant-steps-icon{color:#e34d59}.ant-steps-item-error .ant-steps-item-icon>.ant-steps-icon .ant-steps-icon-dot{background:#e34d59}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title{color:#e34d59}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{background-color:#f0f0f0}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-description{color:#e34d59}.ant-steps-item-error>.ant-steps-item-container>.ant-steps-item-tail:after{background-color:#f0f0f0}.ant-steps-item.ant-steps-next-error .ant-steps-item-title:after{background:#e34d59}.ant-steps-item-disabled{cursor:not-allowed}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]{cursor:pointer}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-title,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-description,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button] .ant-steps-item-icon .ant-steps-icon{transition:color .3s}.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-title,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-subtitle,.ant-steps .ant-steps-item:not(.ant-steps-item-active)>.ant-steps-item-container[role=button]:hover .ant-steps-item-description{color:#0052d9}.ant-steps .ant-steps-item:not(.ant-steps-item-active):not(.ant-steps-item-process)>.ant-steps-item-container[role=button]:hover .ant-steps-item-icon{border-color:#0052d9}.ant-steps .ant-steps-item:not(.ant-steps-item-active):not(.ant-steps-item-process)>.ant-steps-item-container[role=button]:hover .ant-steps-item-icon .ant-steps-icon{color:#0052d9}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:16px;white-space:nowrap}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-right:0}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child .ant-steps-item-title{padding-right:0}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item-tail{display:none}.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item-description{max-width:140px;white-space:normal}.ant-steps-item-custom .ant-steps-item-icon{height:auto;background:none;border:0}.ant-steps-item-custom .ant-steps-item-icon>.ant-steps-icon{top:0px;left:.5px;width:32px;height:32px;font-size:24px;line-height:32px}.ant-steps-item-custom.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon{color:#0052d9}.ant-steps:not(.ant-steps-vertical) .ant-steps-item-custom .ant-steps-item-icon{width:auto;background:none}.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:12px}.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-right:0}.ant-steps-small .ant-steps-item-icon{width:24px;height:24px;margin:0 8px 0 0;font-size:12px;line-height:24px;text-align:center;border-radius:24px}.ant-steps-small .ant-steps-item-title{padding-right:12px;font-size:14px;line-height:24px}.ant-steps-small .ant-steps-item-title:after{top:12px}.ant-steps-small .ant-steps-item-description{color:#000a2999;font-size:14px}.ant-steps-small .ant-steps-item-tail{top:8px}.ant-steps-small .ant-steps-item-custom .ant-steps-item-icon{width:inherit;height:inherit;line-height:inherit;background:none;border:0;border-radius:0}.ant-steps-small .ant-steps-item-custom .ant-steps-item-icon>.ant-steps-icon{font-size:24px;line-height:24px;transform:none}.ant-steps-vertical{display:flex;flex-direction:column}.ant-steps-vertical .ant-steps-item{display:block;flex:1 0 auto;overflow:visible}.ant-steps-vertical .ant-steps-item-icon{float:left;margin-right:16px}.ant-steps-vertical .ant-steps-item-content{display:block;min-height:48px;overflow:hidden}.ant-steps-vertical .ant-steps-item-title{line-height:32px}.ant-steps-vertical .ant-steps-item-description{padding-bottom:12px}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{position:absolute;top:0;left:16px;width:1px;height:100%;padding:38px 0 6px}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail:after{width:1px;height:100%}.ant-steps-vertical>.ant-steps-item:not(:last-child)>.ant-steps-item-container>.ant-steps-item-tail{display:block}.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-vertical.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{position:absolute;top:0;left:12px;padding:30px 0 6px}.ant-steps-vertical.ant-steps-small .ant-steps-item-container .ant-steps-item-title{line-height:24px}.ant-steps-rtl.ant-steps-vertical .ant-steps-item-icon{float:right;margin-right:0;margin-left:16px}.ant-steps-rtl.ant-steps-vertical>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{right:16px;left:auto}.ant-steps-rtl.ant-steps-vertical.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{right:12px;left:auto}@media (max-width: 480px){.ant-steps-horizontal.ant-steps-label-horizontal{display:flex;flex-direction:column}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item{display:block;flex:1 0 auto;overflow:visible}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-icon{float:left;margin-right:16px}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-content{display:block;min-height:48px;overflow:hidden}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-title{line-height:32px}.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-description{padding-bottom:12px}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{position:absolute;top:0;left:16px;width:1px;height:100%;padding:38px 0 6px}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail:after{width:1px;height:100%}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item:not(:last-child)>.ant-steps-item-container>.ant-steps-item-tail{display:block}.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title:after{display:none}.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{position:absolute;top:0;left:12px;padding:30px 0 6px}.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item-container .ant-steps-item-title{line-height:24px}.ant-steps-rtl.ant-steps-horizontal.ant-steps-label-horizontal .ant-steps-item-icon{float:right;margin-right:0;margin-left:16px}.ant-steps-rtl.ant-steps-horizontal.ant-steps-label-horizontal>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{right:16px;left:auto}.ant-steps-rtl.ant-steps-horizontal.ant-steps-label-horizontal.ant-steps-small .ant-steps-item-container .ant-steps-item-tail{right:12px;left:auto}}.ant-steps-label-vertical .ant-steps-item{overflow:visible}.ant-steps-label-vertical .ant-steps-item-tail{margin-left:58px;padding:3.5px 24px}.ant-steps-label-vertical .ant-steps-item-content{display:block;width:116px;margin-top:8px;text-align:center}.ant-steps-label-vertical .ant-steps-item-icon{display:inline-block;margin-left:42px}.ant-steps-label-vertical .ant-steps-item-title{padding-right:0;padding-left:0}.ant-steps-label-vertical .ant-steps-item-title:after{display:none}.ant-steps-label-vertical .ant-steps-item-subtitle{display:block;margin-bottom:4px;margin-left:0;line-height:1.5715}.ant-steps-label-vertical.ant-steps-small:not(.ant-steps-dot) .ant-steps-item-icon{margin-left:46px}.ant-steps-dot .ant-steps-item-title,.ant-steps-dot.ant-steps-small .ant-steps-item-title{line-height:1.5715}.ant-steps-dot .ant-steps-item-tail,.ant-steps-dot.ant-steps-small .ant-steps-item-tail{top:2px;width:100%;margin:0 0 0 70px;padding:0}.ant-steps-dot .ant-steps-item-tail:after,.ant-steps-dot.ant-steps-small .ant-steps-item-tail:after{width:calc(100% - 20px);height:3px;margin-left:12px}.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot,.ant-steps-dot.ant-steps-small .ant-steps-item:first-child .ant-steps-icon-dot{left:2px}.ant-steps-dot .ant-steps-item-icon,.ant-steps-dot.ant-steps-small .ant-steps-item-icon{width:8px;height:8px;margin-left:67px;padding-right:0;line-height:8px;background:transparent;border:0}.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot,.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot{position:relative;float:left;width:100%;height:100%;border-radius:100px;transition:all .3s}.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot:after,.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot:after{position:absolute;top:-12px;left:-26px;width:60px;height:32px;background:rgba(0,0,0,.001);content:""}.ant-steps-dot .ant-steps-item-content,.ant-steps-dot.ant-steps-small .ant-steps-item-content{width:140px}.ant-steps-dot .ant-steps-item-process .ant-steps-item-icon,.ant-steps-dot.ant-steps-small .ant-steps-item-process .ant-steps-item-icon{position:relative;top:-1px;width:10px;height:10px;line-height:10px}.ant-steps-vertical.ant-steps-dot .ant-steps-item-icon{margin-top:8px;margin-left:0;background:none}.ant-steps-vertical.ant-steps-dot .ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{top:2px;left:-9px;margin:0;padding:22px 0 4px}.ant-steps-vertical.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot{left:0}.ant-steps-vertical.ant-steps-dot .ant-steps-item-process .ant-steps-icon-dot{left:-2px}.ant-steps-navigation{padding-top:12px}.ant-steps-navigation.ant-steps-small .ant-steps-item-container{margin-left:-12px}.ant-steps-navigation .ant-steps-item{overflow:visible;text-align:center}.ant-steps-navigation .ant-steps-item-container{display:inline-block;height:100%;margin-left:-16px;padding-bottom:12px;text-align:left;transition:opacity .3s}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-content{max-width:auto}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-title{max-width:100%;padding-right:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-steps-navigation .ant-steps-item-container .ant-steps-item-title:after{display:none}.ant-steps-navigation .ant-steps-item:not(.ant-steps-item-active) .ant-steps-item-container[role=button]{cursor:pointer}.ant-steps-navigation .ant-steps-item:not(.ant-steps-item-active) .ant-steps-item-container[role=button]:hover{opacity:.85}.ant-steps-navigation .ant-steps-item:last-child{flex:1}.ant-steps-navigation .ant-steps-item:last-child:after{display:none}.ant-steps-navigation .ant-steps-item:after{position:absolute;top:50%;left:100%;display:inline-block;width:12px;height:12px;margin-top:-14px;margin-left:-2px;border:1px solid rgba(0,0,0,.25);border-bottom:none;border-left:none;transform:rotate(45deg);content:""}.ant-steps-navigation .ant-steps-item:before{position:absolute;bottom:0;left:50%;display:inline-block;width:0;height:3px;background-color:#0052d9;transition:width .3s,left .3s;transition-timing-function:ease-out;content:""}.ant-steps-navigation .ant-steps-item.ant-steps-item-active:before{left:0;width:100%}@media (max-width: 480px){.ant-steps-navigation>.ant-steps-item{margin-right:0!important}.ant-steps-navigation>.ant-steps-item:before{display:none}.ant-steps-navigation>.ant-steps-item.ant-steps-item-active:before{top:0;right:0;left:unset;display:block;width:3px;height:calc(100% - 24px)}.ant-steps-navigation>.ant-steps-item:after{position:relative;top:-2px;left:50%;display:block;width:8px;height:8px;margin-bottom:8px;text-align:center;transform:rotate(135deg)}.ant-steps-navigation>.ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{visibility:hidden}}.ant-steps-rtl{direction:rtl}.ant-steps.ant-steps-rtl .ant-steps-item-icon{margin-right:0;margin-left:8px}.ant-steps-rtl .ant-steps-item-tail{right:0;left:auto}.ant-steps-rtl .ant-steps-item-title{padding-right:0;padding-left:16px}.ant-steps-rtl .ant-steps-item-title:after{right:100%;left:auto}.ant-steps-rtl.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:0;margin-left:16px}.ant-steps-rtl.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-left:0}.ant-steps-rtl.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child .ant-steps-item-title{padding-left:0}.ant-steps-rtl .ant-steps-item-custom .ant-steps-item-icon>.ant-steps-icon{right:.5px;left:auto}.ant-steps-rtl.ant-steps-navigation.ant-steps-small .ant-steps-item-container{margin-right:-12px;margin-left:0}.ant-steps-rtl.ant-steps-navigation .ant-steps-item-container{margin-right:-16px;margin-left:0;text-align:right}.ant-steps-rtl.ant-steps-navigation .ant-steps-item-container .ant-steps-item-title{padding-left:0}.ant-steps-rtl.ant-steps-navigation .ant-steps-item:after{right:100%;left:auto;margin-right:-2px;margin-left:0;transform:rotate(225deg)}.ant-steps-rtl.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item{margin-right:0;margin-left:12px}.ant-steps-rtl.ant-steps-small.ant-steps-horizontal:not(.ant-steps-label-vertical) .ant-steps-item:last-child{margin-left:0}.ant-steps-rtl.ant-steps-small .ant-steps-item-title{padding-right:0;padding-left:12px}.ant-steps-rtl.ant-steps-label-vertical .ant-steps-item-title{padding-left:0}.ant-steps-rtl.ant-steps-dot .ant-steps-item-tail,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item-tail{margin:0 70px 0 0}.ant-steps-rtl.ant-steps-dot .ant-steps-item-tail:after,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item-tail:after{margin-right:12px;margin-left:0}.ant-steps-rtl.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item:first-child .ant-steps-icon-dot{right:2px;left:auto}.ant-steps-rtl.ant-steps-dot .ant-steps-item-icon,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item-icon{margin-right:67px;margin-left:0}.ant-steps-rtl.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot{float:right}.ant-steps-rtl.ant-steps-dot .ant-steps-item-icon .ant-steps-icon-dot:after,.ant-steps-rtl.ant-steps-dot.ant-steps-small .ant-steps-item-icon .ant-steps-icon-dot:after{right:-26px;left:auto}.ant-steps-rtl.ant-steps-vertical.ant-steps-dot .ant-steps-item-icon{margin-right:0;margin-left:16px}.ant-steps-rtl.ant-steps-vertical.ant-steps-dot .ant-steps-item>.ant-steps-item-container>.ant-steps-item-tail{right:-9px;left:auto}.ant-steps-rtl.ant-steps-vertical.ant-steps-dot .ant-steps-item:first-child .ant-steps-icon-dot{right:0;left:auto}.ant-steps-rtl.ant-steps-vertical.ant-steps-dot .ant-steps-item-process .ant-steps-icon-dot{right:-2px;left:auto}.ant-switch{margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:inline-block;box-sizing:border-box;min-width:44px;height:22px;line-height:20px;vertical-align:middle;background-color:#bec1cf;border:1px solid transparent;border-radius:100px;cursor:pointer;transition:all .2s;user-select:none}.ant-switch-inner{display:block;margin-right:7px;margin-left:25px;color:#adbacc;font-size:12px}.ant-switch-loading-icon,.ant-switch:after{position:absolute;top:2px;left:2px;width:16px;height:16px;background-color:#fff;border-radius:18px;cursor:pointer;transition:all .2s ease-in-out;content:" "}.ant-switch:not(.ant-switch-disabled):active:before,.ant-switch:not(.ant-switch-disabled):active:after{width:12px}.ant-switch-loading-icon{z-index:1;display:none;font-size:12px;background:transparent}.ant-switch-loading-icon svg{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto}.ant-switch-loading .ant-switch-loading-icon{display:inline-block;color:#000000a6}.ant-switch-checked.ant-switch-loading .ant-switch-loading-icon{color:#fff}.ant-switch:focus{outline:0;box-shadow:0 0 0 2px #0052d933}.ant-switch:focus:hover{box-shadow:none}.ant-switch-small{min-width:36px;height:20px;line-height:18px}.ant-switch-small .ant-switch-inner{margin-right:3px;margin-left:18px;font-size:12px}.ant-switch-small:after{width:14px;height:14px}.ant-switch-small:active:before,.ant-switch-small:active:after{width:16px}.ant-switch-small .ant-switch-loading-icon{width:14px;height:14px}.ant-switch-small.ant-switch-checked .ant-switch-inner{margin-right:18px;margin-left:3px}.ant-switch-small.ant-switch-checked .ant-switch-loading-icon{left:100%;margin-left:-17px}.ant-switch-small.ant-switch-loading .ant-switch-loading-icon{font-weight:700}.ant-switch-checked{background-color:#0052d9;border:1px solid transparent}.ant-switch-checked .ant-switch-inner{margin-right:25px;margin-left:7px;color:#fff}.ant-switch-checked:after{left:100%;margin-left:-2px;background-color:#fff;transform:translate(-100%)}.ant-switch-loading{background-color:#e6e9ed}.ant-switch-loading:after{background-color:#e6e9ed}.ant-switch-checked .ant-switch-loading-icon{left:100%;margin-left:-19px}.ant-switch-loading.ant-switch-checked{background-color:#0052d9}.ant-switch-loading.ant-switch-checked:after{background-color:#0052d9}.ant-switch-loading,.ant-switch-disabled{background-color:#e6e9ed;cursor:not-allowed;opacity:.4}.ant-switch-checked.ant-switch-loading,.ant-switch-checked.ant-switch-disabled{background-color:#0052d9}.ant-switch-loading *,.ant-switch-disabled *{cursor:not-allowed}.ant-switch-loading:before,.ant-switch-disabled:before,.ant-switch-loading:after,.ant-switch-disabled:after{cursor:not-allowed}.ant-switch-rtl{direction:rtl}.ant-switch-rtl .ant-switch-inner{margin-right:25px;margin-left:7px}.ant-switch-rtl.ant-switch-loading-icon,.ant-switch-rtl.ant-switch:after{left:100%;margin-left:-1px;transform:translate(-100%)}.ant-switch-rtl.ant-switch-small .ant-switch-inner{margin-right:18px;margin-left:3px}.ant-switch-rtl.ant-switch-small .ant-switch-loading-icon{margin-left:12px}.ant-switch-rtl.ant-switch-small.ant-switch-checked .ant-switch-inner{margin-right:3px;margin-left:18px}.ant-switch-rtl.ant-switch-checked .ant-switch-inner{margin-right:7px;margin-left:25px}.ant-switch-rtl.ant-switch-checked:after{left:1px;margin-left:0;transform:translate(0)}.ant-switch-rtl.ant-switch-checked .ant-switch-loading-icon{margin-left:-41px}.ant-table.ant-table-middle{font-size:14px}.ant-table.ant-table-middle .ant-table-title,.ant-table.ant-table-middle .ant-table-footer,.ant-table.ant-table-middle .ant-table-thead>tr>th,.ant-table.ant-table-middle .ant-table-tbody>tr>td,.ant-table.ant-table-middle tfoot>tr>th,.ant-table.ant-table-middle tfoot>tr>td{padding:9px 6px}.ant-table.ant-table-middle .ant-table-thead>tr>th{padding:10px 6px}.ant-table.ant-table-middle .ant-table-thead th.ant-table-column-has-sorters{padding:0}.ant-table.ant-table-middle .ant-table-thead .ant-table-filter-column{margin:-9px -6px}.ant-table.ant-table-middle .ant-table-thead .ant-table-filter-column-title{padding:9px 2.3em 9px 6px}.ant-table.ant-table-middle .ant-table-thead .ant-table-column-sorters{padding:9px 6px}.ant-table.ant-table-middle .ant-table-expanded-row-fixed{margin:-9px -6px}.ant-table.ant-table-middle .ant-table-tbody .ant-table-wrapper:only-child .ant-table{margin:-9px -6px -9px 23px}.ant-table.ant-table-small{font-size:14px}.ant-table.ant-table-small .ant-table-title,.ant-table.ant-table-small .ant-table-footer,.ant-table.ant-table-small .ant-table-thead>tr>th,.ant-table.ant-table-small .ant-table-tbody>tr>td,.ant-table.ant-table-small tfoot>tr>th,.ant-table.ant-table-small tfoot>tr>td{padding:11px 6px}.ant-table.ant-table-small .ant-table-thead>tr>th{padding:10px 6px}.ant-table.ant-table-small .ant-table-thead th.ant-table-column-has-sorters{padding:0}.ant-table.ant-table-small .ant-table-thead .ant-table-filter-column{margin:-11px -6px}.ant-table.ant-table-small .ant-table-thead .ant-table-filter-column-title{padding:11px 2.3em 11px 6px}.ant-table.ant-table-small .ant-table-thead .ant-table-column-sorters{padding:11px 6px}.ant-table.ant-table-small .ant-table-expanded-row-fixed{margin:-11px -6px}.ant-table.ant-table-small .ant-table-tbody .ant-table-wrapper:only-child .ant-table{margin:-11px -6px -11px 23px}.ant-table-small .ant-table-thead>tr>th{background-color:#fff}.ant-table-small .ant-table-selection-column{width:46px;min-width:46px}.ant-table-small .ant-empty{font-size:18px}.ant-table-small .ant-empty .ant-empty-description{font-size:12px}.ant-table.ant-table-bordered>.ant-table-title{border:1px solid #f0f2f4;border-bottom:0}.ant-table.ant-table-bordered>.ant-table-container{border:1px solid #f0f2f4;border-right:0;border-bottom:0}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>thead>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>thead>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tbody>tr>td:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tbody>tr>td:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tbody>tr>td:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tfoot>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tfoot>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tfoot>tr>th:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tfoot>tr>td:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tfoot>tr>td:last-child,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tfoot>tr>td:last-child{border-right:1px solid #f0f2f4}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr>th,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>thead>tr>th,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>thead>tr>th{border-top:none;border-bottom:1px solid #f0f2f4}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr:not(:last-child)>th,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>thead>tr:not(:last-child)>th,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>thead>tr:not(:last-child)>th{border-bottom:1px solid #f0f2f4}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>thead>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>thead>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>thead>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tbody>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tbody>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tbody>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tfoot>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tfoot>tr>.ant-table-cell-fix-right-first:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tfoot>tr>.ant-table-cell-fix-right-first:after{border-right:1px solid #f0f2f4}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tbody>tr>td,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tbody>tr>td,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tbody>tr>td{border-bottom:1px solid #f0f2f4}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tbody>tr>td>.ant-table-expanded-row-fixed,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tbody>tr>td>.ant-table-expanded-row-fixed,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tbody>tr>td>.ant-table-expanded-row-fixed{margin:-12px -13px}.ant-table.ant-table-bordered>.ant-table-container>.ant-table-content>table>tbody>tr>td>.ant-table-expanded-row-fixed:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-header>table>tbody>tr>td>.ant-table-expanded-row-fixed:after,.ant-table.ant-table-bordered>.ant-table-container>.ant-table-body>table>tbody>tr>td>.ant-table-expanded-row-fixed:after{position:absolute;top:0;right:1px;bottom:0;border-right:1px solid #f0f2f4;content:""}.ant-table.ant-table-bordered.ant-table-scroll-horizontal>.ant-table-container>.ant-table-body>table>tbody>tr.ant-table-expanded-row>td,.ant-table.ant-table-bordered.ant-table-scroll-horizontal>.ant-table-container>.ant-table-body>table>tbody>tr.ant-table-placeholder>td{border-right:0}.ant-table.ant-table-bordered.ant-table-middle>.ant-table-container>.ant-table-content>table>tbody>tr>td>.ant-table-expanded-row-fixed,.ant-table.ant-table-bordered.ant-table-middle>.ant-table-container>.ant-table-body>table>tbody>tr>td>.ant-table-expanded-row-fixed{margin:-9px -7px}.ant-table.ant-table-bordered.ant-table-small>.ant-table-container>.ant-table-content>table>tbody>tr>td>.ant-table-expanded-row-fixed,.ant-table.ant-table-bordered.ant-table-small>.ant-table-container>.ant-table-body>table>tbody>tr>td>.ant-table-expanded-row-fixed{margin:-9px -7px}.ant-table.ant-table-bordered>.ant-table-footer{border:1px solid #f0f2f4;border-top:0}.ant-table-cell .ant-table-container:first-child{border-top:0}.ant-table-cell-scrollbar{box-shadow:0 1px 0 1px #fff}.ant-table-wrapper{clear:both;max-width:100%}.ant-table-wrapper:before{display:table;content:""}.ant-table-wrapper:after{display:table;clear:both;content:""}.ant-table{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;z-index:0;font-size:14px;background:#fff;border-radius:3px}.ant-table table{width:100%;text-align:left;border-radius:3px 3px 0 0;border-collapse:separate;border-spacing:0}.ant-table-thead>tr>th,.ant-table-tbody>tr>td,.ant-table tfoot>tr>th,.ant-table tfoot>tr>td{position:relative;padding:12px;overflow-wrap:break-word}.ant-table-cell-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.ant-table-cell-ellipsis.ant-table-cell-fix-left-last,.ant-table-cell-ellipsis.ant-table-cell-fix-right-first{overflow:visible}.ant-table-cell-ellipsis.ant-table-cell-fix-left-last .ant-table-cell-content,.ant-table-cell-ellipsis.ant-table-cell-fix-right-first .ant-table-cell-content{display:block;overflow:hidden;text-overflow:ellipsis}.ant-table-title{padding:12px}.ant-table-footer{padding:12px;color:#000a2999;background:#f1f2f5}.ant-table-thead>tr>th{padding:14px 12px;color:#000a2999;font-weight:400;font-size:14px;text-align:left;background:#fff;border-top:1px solid #e6e9ed;border-bottom:1px solid #f5f7fa;transition:background .3s ease}.ant-table-thead>tr>th[colspan]:not([colspan="1"]){text-align:center}.ant-table-thead>tr:not(:last-child)>th[colspan]{border-bottom:0}.ant-table-tbody>tr>td{border-bottom:1px solid #f0f0f0;transition:background .3s}.ant-table-tbody>tr>td>.ant-table-wrapper:only-child .ant-table{margin:-12px -12px -12px 29px}.ant-table-tbody>tr>td>.ant-table-wrapper:only-child .ant-table-tbody>tr:last-child>td{border-bottom:0}.ant-table-tbody>tr>td>.ant-table-wrapper:only-child .ant-table-tbody>tr:last-child>td:first-child,.ant-table-tbody>tr>td>.ant-table-wrapper:only-child .ant-table-tbody>tr:last-child>td:last-child{border-radius:0}.ant-table-tbody>tr>td>.ant-table-wrapper:only-child .ant-table-thead>tr>th{border-top:none}.ant-table-tbody>tr.ant-table-row:hover>td{background:#f1f2f5}.ant-table-tbody>tr.ant-table-row-selected>td{border-color:#00000008}.ant-table-tbody>tr.ant-table-row-selected:hover>td{background:#f5f7fa}.ant-table tfoot>tr>th,.ant-table tfoot>tr>td{border-bottom:1px solid #f0f0f0}.ant-table-pagination.ant-pagination{margin:16px 0}.ant-table-pagination{display:flex}.ant-table-pagination-left{justify-content:flex-start}.ant-table-pagination-center{justify-content:center}.ant-table-pagination-right{justify-content:flex-end}.ant-table-thead th.ant-table-column-has-sorters{padding:0;cursor:pointer;transition:all .3s}.ant-table-thead th.ant-table-column-has-sorters:hover{background:#f7f7f7}.ant-table-thead th.ant-table-column-has-sorters:hover .ant-table-filter-trigger-container{background:#f5f7fa}.ant-table-thead th.ant-table-column-sort{background:#f5f5f5}.ant-table-column-sorters-with-tooltip{display:inline-block;width:100%}.ant-table-column-sorters{display:inline-flex;align-items:center;padding:12px}.ant-table-column-sorter{margin-top:.15em;margin-bottom:-.15em;margin-left:8px;color:#c5cedb}.ant-table-column-sorter-full{margin-top:-.2em;margin-bottom:0}.ant-table-column-sorter-inner{display:inline-flex;flex-direction:column;align-items:center}.ant-table-column-sorter-up,.ant-table-column-sorter-down{display:inline-block;font-size:11px}.ant-table-column-sorter-up.active,.ant-table-column-sorter-down.active{color:#0052d9}.ant-table-column-sorter-up+.ant-table-column-sorter-down{margin-top:-.3em}.ant-table-filter-column{display:flex;align-items:center;margin:-12px}.ant-table-filter-column-title{flex:auto;padding:12px 2.3em 12px 12px}.ant-table-thead tr th.ant-table-column-has-sorters .ant-table-filter-column{margin:0}.ant-table-thead tr th.ant-table-column-has-sorters .ant-table-filter-column-title{padding:0 2.3em 0 0}.ant-table-filter-trigger-container{position:absolute;top:0;right:0;bottom:0;display:flex;flex:none;align-items:stretch;align-self:stretch;cursor:pointer;transition:background-color .3s}.ant-table-filter-trigger-container-open,.ant-table-filter-trigger-container:hover,.ant-table-thead th.ant-table-column-has-sorters:hover .ant-table-filter-trigger-container:hover{background:#ebebeb}.ant-table-filter-trigger{display:block;width:2.3em;color:#c5cedb;font-size:12px;transition:color .3s}.ant-table-filter-trigger .anticon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.ant-table-filter-trigger-container-open .ant-table-filter-trigger,.ant-table-filter-trigger:hover{color:#000a2999}.ant-table-filter-trigger.active{color:#0052d9}.ant-table-filter-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";min-width:120px;background-color:#fff;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-table-filter-dropdown .ant-dropdown-menu{max-height:264px;overflow-x:hidden;border:0;box-shadow:none}.ant-table-filter-dropdown-submenu>ul{max-height:calc(100vh - 130px);overflow-x:hidden;overflow-y:auto}.ant-table-filter-dropdown .ant-checkbox-wrapper+span,.ant-table-filter-dropdown-submenu .ant-checkbox-wrapper+span{padding-left:8px}.ant-table-filter-dropdown-btns{display:flex;justify-content:space-between;padding:7px 8px 7px 12px;overflow:hidden;background-color:inherit;border-top:1px solid #f0f0f0}.ant-table .ant-table-selection-col{width:60px}table tr th.ant-table-selection-column,table tr td.ant-table-selection-column{padding-right:0;padding-left:8px;text-align:center}table tr th.ant-table-selection-column .ant-radio-wrapper,table tr td.ant-table-selection-column .ant-radio-wrapper{margin-right:0}.ant-table-selection{position:relative}.ant-table-selection-extra{position:absolute;top:4px;right:-2px;cursor:pointer;transition:all .3s}.ant-table-selection-extra .anticon{color:#c5cedb;font-size:14px}.ant-table-selection-extra .anticon:hover{color:#202d40}.ant-table-expand-icon-col{width:48px}.ant-table-row-expand-icon-cell{text-align:center}.ant-table-row-indent{float:left;height:1px}.ant-table-row-expand-icon{color:#0052d9;text-decoration:none;cursor:pointer;transition:color .3s;position:relative;display:inline-flex;float:left;box-sizing:border-box;width:17px;height:17px;padding:0;color:inherit;line-height:17px;background:#fff;border:1px solid #f0f0f0;border-radius:3px;outline:none;transition:all .3s;user-select:none}.ant-table-row-expand-icon:focus,.ant-table-row-expand-icon:hover{color:#2575e6}.ant-table-row-expand-icon:active{color:#003eb3}.ant-table-row-expand-icon:focus,.ant-table-row-expand-icon:hover,.ant-table-row-expand-icon:active{border-color:currentColor}.ant-table-row-expand-icon:before,.ant-table-row-expand-icon:after{position:absolute;background:currentColor;transition:transform .3s ease-out;content:""}.ant-table-row-expand-icon:before{top:7px;right:3px;left:3px;height:1px}.ant-table-row-expand-icon:after{top:3px;bottom:3px;left:7px;width:1px;transform:rotate(90deg)}.ant-table-row-expand-icon-collapsed:before{transform:rotate(-180deg)}.ant-table-row-expand-icon-collapsed:after{transform:rotate(0)}.ant-table-row-expand-icon-spaced{background:transparent;border:0;visibility:hidden}.ant-table-row-expand-icon-spaced:before,.ant-table-row-expand-icon-spaced:after{display:none;content:none}.ant-table-row-indent+.ant-table-row-expand-icon{margin-top:2.5005px;margin-right:8px}tr.ant-table-expanded-row>td,tr.ant-table-expanded-row:hover>td{background:#fbfbfb}tr.ant-table-expanded-row .ant-descriptions-view table{width:auto}.ant-table .ant-table-expanded-row-fixed{position:relative;margin:-12px;padding:12px}.ant-table-tbody>tr.ant-table-placeholder{text-align:center}.ant-table-empty .ant-table-tbody>tr.ant-table-placeholder{color:#00000040}.ant-table-tbody>tr.ant-table-placeholder:hover>td{background:#fff}.ant-table-cell-fix-left,.ant-table-cell-fix-right{position:-webkit-sticky!important;position:sticky!important;z-index:2;background:#fff}.ant-table-cell-fix-left-first:after,.ant-table-cell-fix-left-last:after{position:absolute;top:0;right:0;bottom:-1px;width:30px;transform:translate(100%);transition:box-shadow .3s;content:"";pointer-events:none}.ant-table-cell-fix-right-first:after,.ant-table-cell-fix-right-last:after{position:absolute;top:0;bottom:-1px;left:0;width:30px;transform:translate(-100%);transition:box-shadow .3s;content:"";pointer-events:none}.ant-table .ant-table-container:before,.ant-table .ant-table-container:after{position:absolute;top:0;bottom:0;z-index:1;width:30px;transition:box-shadow .3s;content:"";pointer-events:none}.ant-table .ant-table-container:before{left:0}.ant-table .ant-table-container:after{right:0}.ant-table-ping-left:not(.ant-table-has-fix-left) .ant-table-container{position:relative}.ant-table-ping-left:not(.ant-table-has-fix-left) .ant-table-container:before{box-shadow:inset 10px 0 8px -8px #00000026}.ant-table-ping-left .ant-table-cell-fix-left-first:after,.ant-table-ping-left .ant-table-cell-fix-left-last:after{box-shadow:inset 10px 0 8px -8px #00000026}.ant-table-ping-right:not(.ant-table-has-fix-right) .ant-table-container{position:relative}.ant-table-ping-right:not(.ant-table-has-fix-right) .ant-table-container:after{box-shadow:inset -10px 0 8px -8px #00000026}.ant-table-ping-right .ant-table-cell-fix-right-first:after,.ant-table-ping-right .ant-table-cell-fix-right-last:after{box-shadow:inset -10px 0 8px -8px #00000026}.ant-table-sticky-header{position:sticky;z-index:3}.ant-table-sticky-scroll{position:fixed;bottom:0;z-index:3;display:flex;align-items:center;background:#ffffff;border-top:1px solid #f0f0f0;opacity:.6}.ant-table-sticky-scroll:hover{transform-origin:center bottom}.ant-table-sticky-scroll-bar{height:8px;background-color:#00000059;border-radius:4px}.ant-table-sticky-scroll-bar:hover,.ant-table-sticky-scroll-bar-active{background-color:#f5f7fa}@media all and (-ms-high-contrast: none){.ant-table-ping-left .ant-table-cell-fix-left-last:after{box-shadow:none!important}.ant-table-ping-right .ant-table-cell-fix-right-first:after{box-shadow:none!important}}.ant-table-title{border-radius:3px 3px 0 0}.ant-table-title+.ant-table-container{border-top-left-radius:0;border-top-right-radius:0}.ant-table-title+.ant-table-container table>thead>tr:first-child th:first-child{border-radius:0}.ant-table-title+.ant-table-container table>thead>tr:first-child th:last-child{border-radius:0}.ant-table-container{border-top-left-radius:3px;border-top-right-radius:3px}.ant-table-container table>thead>tr:first-child th:first-child{border-top-left-radius:3px}.ant-table-container table>thead>tr:first-child th:last-child{border-top-right-radius:3px}.ant-table-footer{border-radius:0 0 3px 3px}.ant-table-wrapper-rtl,.ant-table-rtl{direction:rtl}.ant-table-wrapper-rtl .ant-table table{text-align:right}.ant-table-wrapper-rtl .ant-table-thead>tr>th[colspan]:not([colspan="1"]){text-align:center}.ant-table-wrapper-rtl .ant-table-thead>tr>th{text-align:right}.ant-table-tbody>tr .ant-table-wrapper:only-child .ant-table.ant-table-rtl{margin:-12px 29px -12px -12px}.ant-table-wrapper.ant-table-wrapper-rtl .ant-table-pagination-left{justify-content:flex-end}.ant-table-wrapper.ant-table-wrapper-rtl .ant-table-pagination-right{justify-content:flex-start}.ant-table-wrapper-rtl .ant-table-column-sorter{margin-right:8px;margin-left:0}.ant-table-wrapper-rtl .ant-table-filter-column-title{padding:12px 12px 12px 2.3em}.ant-table-rtl .ant-table-thead tr th.ant-table-column-has-sorters .ant-table-filter-column-title{padding:0 0 0 2.3em}.ant-table-wrapper-rtl .ant-table-filter-trigger-container{right:auto;left:0}.ant-dropdown-rtl .ant-table-filter-dropdown .ant-checkbox-wrapper+span,.ant-dropdown-rtl .ant-table-filter-dropdown-submenu .ant-checkbox-wrapper+span,.ant-dropdown-menu-submenu-rtl.ant-table-filter-dropdown .ant-checkbox-wrapper+span,.ant-dropdown-menu-submenu-rtl.ant-table-filter-dropdown-submenu .ant-checkbox-wrapper+span{padding-right:8px;padding-left:0}.ant-table-wrapper-rtl .ant-table-selection{text-align:center}.ant-table-wrapper-rtl .ant-table-selection-extra{right:auto;left:0}.ant-table-wrapper-rtl .ant-table-row-indent,.ant-table-wrapper-rtl .ant-table-row-expand-icon{float:right}.ant-table-wrapper-rtl .ant-table-row-indent+.ant-table-row-expand-icon{margin-right:0;margin-left:8px}.ant-table-wrapper-rtl .ant-table-row-expand-icon:after{transform:rotate(-90deg)}.ant-table-wrapper-rtl .ant-table-row-expand-icon-collapsed:before{transform:rotate(180deg)}.ant-table-wrapper-rtl .ant-table-row-expand-icon-collapsed:after{transform:rotate(0)}.ant-tabs-small>.ant-tabs-nav .ant-tabs-tab{padding:8px 0;font-size:14px}.ant-tabs-large>.ant-tabs-nav .ant-tabs-tab{padding:16px 0;font-size:16px}.ant-tabs-card.ant-tabs-small>.ant-tabs-nav .ant-tabs-tab{padding:6px 16px}.ant-tabs-card.ant-tabs-large>.ant-tabs-nav .ant-tabs-tab{padding:7px 16px 6px}.ant-tabs-rtl{direction:rtl}.ant-tabs-rtl .ant-tabs-nav .ant-tabs-tab{margin:0 0 0 32px}.ant-tabs-rtl .ant-tabs-nav .ant-tabs-tab:last-of-type{margin-left:0}.ant-tabs-rtl .ant-tabs-nav .ant-tabs-tab .anticon{margin-right:0;margin-left:12px}.ant-tabs-rtl .ant-tabs-nav .ant-tabs-tab .ant-tabs-tab-remove{margin-right:8px;margin-left:-4px}.ant-tabs-rtl .ant-tabs-nav .ant-tabs-tab .ant-tabs-tab-remove .anticon{margin:0}.ant-tabs-rtl.ant-tabs-left>.ant-tabs-nav{order:1}.ant-tabs-rtl.ant-tabs-left>.ant-tabs-content-holder{order:0}.ant-tabs-rtl.ant-tabs-right>.ant-tabs-nav{order:0}.ant-tabs-rtl.ant-tabs-right>.ant-tabs-content-holder{order:1}.ant-tabs-rtl.ant-tabs-card.ant-tabs-top>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-rtl.ant-tabs-card.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-rtl.ant-tabs-card.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-rtl.ant-tabs-card.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type){margin-right:0;margin-left:2px}.ant-tabs-dropdown-rtl{direction:rtl}.ant-tabs-dropdown-rtl .ant-tabs-dropdown-menu-item{text-align:right}.ant-tabs-top,.ant-tabs-bottom{flex-direction:column}.ant-tabs-top>.ant-tabs-nav,.ant-tabs-bottom>.ant-tabs-nav,.ant-tabs-top>div>.ant-tabs-nav,.ant-tabs-bottom>div>.ant-tabs-nav{margin:0 0 16px}.ant-tabs-top>.ant-tabs-nav:before,.ant-tabs-bottom>.ant-tabs-nav:before,.ant-tabs-top>div>.ant-tabs-nav:before,.ant-tabs-bottom>div>.ant-tabs-nav:before{position:absolute;right:0;left:0;border-bottom:1px solid #f0f0f0;content:""}.ant-tabs-top>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-ink-bar{height:2px}.ant-tabs-top>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-ink-bar-animated{transition:width .3s,left .3s,right .3s}.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap:after{top:0;bottom:0;width:30px}.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap:before{left:0;box-shadow:inset 10px 0 8px -8px #00000014}.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap:after{right:0;box-shadow:inset -10px 0 8px -8px #00000014}.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-left:before,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-left:before,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-left:before,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-left:before{opacity:1}.ant-tabs-top>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-right:after,.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-right:after,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-right:after,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-right:after{opacity:1}.ant-tabs-top>.ant-tabs-nav:before,.ant-tabs-top>div>.ant-tabs-nav:before{bottom:0}.ant-tabs-top>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-ink-bar{bottom:0}.ant-tabs-bottom>.ant-tabs-nav,.ant-tabs-bottom>div>.ant-tabs-nav{order:1;margin-top:16px;margin-bottom:0}.ant-tabs-bottom>.ant-tabs-nav:before,.ant-tabs-bottom>div>.ant-tabs-nav:before{top:0}.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-ink-bar{top:0}.ant-tabs-bottom>.ant-tabs-content-holder,.ant-tabs-bottom>div>.ant-tabs-content-holder{order:0}.ant-tabs-left>.ant-tabs-nav,.ant-tabs-right>.ant-tabs-nav,.ant-tabs-left>div>.ant-tabs-nav,.ant-tabs-right>div>.ant-tabs-nav{flex-direction:column;min-width:50px}.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-right>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-tab{margin:0 0 16px;padding:8px 24px;text-align:center}.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab:last-of-type,.ant-tabs-right>.ant-tabs-nav .ant-tabs-tab:last-of-type,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-tab:last-of-type,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-tab:last-of-type{margin-bottom:0}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap{flex-direction:column}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap:after{right:0;left:0;height:30px}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap:before{top:0;box-shadow:inset 0 10px 8px -8px #00000014}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap:after{bottom:0;box-shadow:inset 0 -10px 8px -8px #00000014}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-top:before,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-top:before,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-top:before,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-top:before{opacity:1}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-bottom:after,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-bottom:after,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-bottom:after,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-wrap.ant-tabs-nav-wrap-ping-bottom:after{opacity:1}.ant-tabs-left>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-right>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-ink-bar{width:2px}.ant-tabs-left>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-right>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-ink-bar-animated,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-ink-bar-animated{transition:height .3s,top .3s}.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-list,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-list,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-list,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-list,.ant-tabs-left>.ant-tabs-nav .ant-tabs-nav-operations,.ant-tabs-right>.ant-tabs-nav .ant-tabs-nav-operations,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-nav-operations,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-nav-operations{flex-direction:column}.ant-tabs-left>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-ink-bar{right:0}.ant-tabs-left>.ant-tabs-content-holder,.ant-tabs-left>div>.ant-tabs-content-holder{margin-left:-1px;border-left:1px solid #f0f0f0}.ant-tabs-left>.ant-tabs-content-holder>.ant-tabs-content>.ant-tabs-tabpane,.ant-tabs-left>div>.ant-tabs-content-holder>.ant-tabs-content>.ant-tabs-tabpane{padding-left:24px}.ant-tabs-right>.ant-tabs-nav,.ant-tabs-right>div>.ant-tabs-nav{order:1}.ant-tabs-right>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-ink-bar{left:0}.ant-tabs-right>.ant-tabs-content-holder,.ant-tabs-right>div>.ant-tabs-content-holder{order:0;margin-right:-1px;border-right:1px solid #f0f0f0}.ant-tabs-right>.ant-tabs-content-holder>.ant-tabs-content>.ant-tabs-tabpane,.ant-tabs-right>div>.ant-tabs-content-holder>.ant-tabs-content>.ant-tabs-tabpane{padding-right:24px}.ant-tabs-dropdown{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;top:-9999px;left:-9999px;z-index:1050;display:block}.ant-tabs-dropdown-hidden{display:none}.ant-tabs-dropdown-menu{max-height:200px;margin:0;padding:4px 0;overflow-x:hidden;overflow-y:auto;text-align:left;list-style-type:none;background-color:#fff;background-clip:padding-box;border-radius:3px;outline:none;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-tabs-dropdown-menu-item{min-width:120px;margin:0;padding:5px 8px;overflow:hidden;color:#000a29e6;font-weight:400;font-size:14px;line-height:22px;white-space:nowrap;text-overflow:ellipsis;cursor:pointer;transition:all .3s}.ant-tabs-dropdown-menu-item:hover{background:#f3f3f3}.ant-tabs-dropdown-menu-item-disabled,.ant-tabs-dropdown-menu-item-disabled:hover{color:#00000040;background:transparent;cursor:not-allowed}.ant-tabs-card>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-card>div>.ant-tabs-nav .ant-tabs-tab{margin:0;padding:8px 16px;background:#f1f2f5;border:1px solid #f0f0f0;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs-card>.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-card>div>.ant-tabs-nav .ant-tabs-tab-active{color:#0052d9;background:#fff}.ant-tabs-card>.ant-tabs-nav .ant-tabs-ink-bar,.ant-tabs-card>div>.ant-tabs-nav .ant-tabs-ink-bar{visibility:hidden}.ant-tabs-card.ant-tabs-top>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type){margin-right:2px}.ant-tabs-card.ant-tabs-top>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-card.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-tab{border-radius:3px 3px 0 0}.ant-tabs-card.ant-tabs-top>.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-card.ant-tabs-top>div>.ant-tabs-nav .ant-tabs-tab-active{border-bottom-color:#fff}.ant-tabs-card.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-card.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-tab{border-radius:0 0 3px 3px}.ant-tabs-card.ant-tabs-bottom>.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-card.ant-tabs-bottom>div>.ant-tabs-nav .ant-tabs-tab-active{border-top-color:#fff}.ant-tabs-card.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-right>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type),.ant-tabs-card.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-tab:not(:last-of-type){margin-bottom:2px}.ant-tabs-card.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-card.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-tab{border-radius:3px 0 0 3px}.ant-tabs-card.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-card.ant-tabs-left>div>.ant-tabs-nav .ant-tabs-tab-active{border-right-color:#fff}.ant-tabs-card.ant-tabs-right>.ant-tabs-nav .ant-tabs-tab,.ant-tabs-card.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-tab{border-radius:0 3px 3px 0}.ant-tabs-card.ant-tabs-right>.ant-tabs-nav .ant-tabs-tab-active,.ant-tabs-card.ant-tabs-right>div>.ant-tabs-nav .ant-tabs-tab-active{border-left-color:#fff}.ant-tabs{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:flex;overflow:hidden}.ant-tabs>.ant-tabs-nav,.ant-tabs>div>.ant-tabs-nav{position:relative;display:flex;flex:none;align-items:center}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-wrap,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-wrap{position:relative;display:inline-block;display:flex;flex:auto;align-self:stretch;overflow:hidden;white-space:nowrap;transform:translate(0)}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-wrap:before,.ant-tabs>.ant-tabs-nav .ant-tabs-nav-wrap:after,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-wrap:after{position:absolute;z-index:1;opacity:0;transition:opacity .3s;content:"";pointer-events:none}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-list,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-list{position:relative;display:flex;transition:transform .3s}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-operations,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-operations{display:flex;align-self:stretch}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-operations-hidden,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-operations-hidden{position:absolute;visibility:hidden;pointer-events:none}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-more,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-more{position:relative;padding:8px 16px;background:transparent;border:0}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-more:after,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-more:after{position:absolute;right:0;bottom:0;left:0;height:5px;transform:translateY(100%);content:""}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-add,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-add{min-width:40px;padding:0 8px;background:#f1f2f5;border:1px solid #f0f0f0;border-radius:3px 3px 0 0;outline:none;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1)}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-add:hover,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-add:hover{color:#2575e6}.ant-tabs>.ant-tabs-nav .ant-tabs-nav-add:active,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-add:active,.ant-tabs>.ant-tabs-nav .ant-tabs-nav-add:focus,.ant-tabs>div>.ant-tabs-nav .ant-tabs-nav-add:focus{color:#003eb3}.ant-tabs-extra-content{flex:none}.ant-tabs-centered>.ant-tabs-nav .ant-tabs-nav-wrap:not([class*="ant-tabs-nav-wrap-ping"]),.ant-tabs-centered>div>.ant-tabs-nav .ant-tabs-nav-wrap:not([class*="ant-tabs-nav-wrap-ping"]){justify-content:center}.ant-tabs-ink-bar{position:absolute;background:#0052d9;pointer-events:none}.ant-tabs-tab{position:relative;display:inline-flex;align-items:center;margin:0 32px 0 0;padding:12px 0;font-size:14px;background:transparent;border:0;outline:none;cursor:pointer}.ant-tabs-tab:last-of-type{margin-right:0;margin-left:0}.ant-tabs-tab-btn:focus,.ant-tabs-tab-remove:focus,.ant-tabs-tab-btn:active,.ant-tabs-tab-remove:active{color:#003eb3}.ant-tabs-tab-btn{outline:none}.ant-tabs-tab-remove{flex:none;margin-right:-4px;margin-left:8px;color:#000a2999;font-size:12px;background:transparent;border:none;outline:none;cursor:pointer;transition:all .3s}.ant-tabs-tab-remove:hover{color:#000a29e6}.ant-tabs-tab:hover{color:#2575e6}.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{color:#0052d9;font-weight:500}.ant-tabs-tab.ant-tabs-tab-disabled{color:#00000040;cursor:not-allowed}.ant-tabs-tab.ant-tabs-tab-disabled .ant-tabs-tab-btn:focus,.ant-tabs-tab.ant-tabs-tab-disabled .ant-tabs-tab-remove:focus,.ant-tabs-tab.ant-tabs-tab-disabled .ant-tabs-tab-btn:active,.ant-tabs-tab.ant-tabs-tab-disabled .ant-tabs-tab-remove:active{color:#00000040}.ant-tabs-tab .ant-tabs-tab-remove .anticon{margin:0}.ant-tabs-tab .anticon{margin-right:12px}.ant-tabs-content{display:flex;width:100%}.ant-tabs-content-holder{flex:auto;min-width:0;min-height:0}.ant-tabs-content-animated{transition:margin .3s}.ant-tabs-tabpane{flex:none;width:100%;outline:none}.ant-tag{box-sizing:border-box;margin:0 8px 0 0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block;height:auto;padding:0 7px;font-size:12px;line-height:20px;white-space:nowrap;background:#f1f2f5;border:1px solid #d9d9d9;border-radius:3px;cursor:default;opacity:1;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-tag:hover{opacity:.85}.ant-tag,.ant-tag a,.ant-tag a:hover{color:#000a29e6}.ant-tag>a:first-child:last-child{display:inline-block;margin:0 -8px;padding:0 8px}.ant-tag .anticon-close{display:inline-block;font-size:10px;margin-left:3px;color:#000a2999;font-weight:700;cursor:pointer;transition:all .3s cubic-bezier(.78,.14,.15,.86)}.ant-tag .anticon-close:hover{color:#000a29e6}.ant-tag-has-color{border-color:transparent}.ant-tag-has-color,.ant-tag-has-color a,.ant-tag-has-color a:hover,.ant-tag-has-color .anticon-close,.ant-tag-has-color .anticon-close:hover{color:#fff}.ant-tag-checkable{background-color:transparent;border-color:transparent;cursor:pointer}.ant-tag-checkable:not(.ant-tag-checkable-checked):hover{color:#0052d9}.ant-tag-checkable:active,.ant-tag-checkable-checked{color:#fff}.ant-tag-checkable-checked{background-color:#0052d9}.ant-tag-checkable:active{background-color:#003eb3}.ant-tag-hidden{display:none}.ant-tag-pink{color:#eb2f96;background:#fff0f6;border-color:#ffadd2}.ant-tag-pink-inverse{color:#fff;background:#eb2f96;border-color:#eb2f96}.ant-tag-magenta{color:#eb2f96;background:#fff0f6;border-color:#ffadd2}.ant-tag-magenta-inverse{color:#fff;background:#eb2f96;border-color:#eb2f96}.ant-tag-red{color:#ca1628;background:#fff0f0;border-color:#fc9c9c}.ant-tag-red-inverse{color:#fff;background:#ca1628;border-color:#ca1628}.ant-tag-volcano{color:#fa541c;background:#fff2e8;border-color:#ffbb96}.ant-tag-volcano-inverse{color:#fff;background:#fa541c;border-color:#fa541c}.ant-tag-orange{color:#cb6b0b;background:#fff4e0;border-color:#fec57c}.ant-tag-orange-inverse{color:#fff;background:#cb6b0b;border-color:#cb6b0b}.ant-tag-yellow{color:#ce9c09;background:#fffbe5;border-color:#fde586}.ant-tag-yellow-inverse{color:#fff;background:#ce9c09;border-color:#ce9c09}.ant-tag-gold{color:#faad14;background:#fffbe6;border-color:#ffe58f}.ant-tag-gold-inverse{color:#fff;background:#faad14;border-color:#faad14}.ant-tag-cyan{color:#0ba4bc;background:#e5feff;border-color:#8ef3fa}.ant-tag-cyan-inverse{color:#fff;background:#0ba4bc;border-color:#0ba4bc}.ant-tag-lime{color:#a0d911;background:#fcffe6;border-color:#eaff8f}.ant-tag-lime-inverse{color:#fff;background:#a0d911;border-color:#a0d911}.ant-tag-green{color:#3ea00e;background:#f2ffe0;border-color:#adf269}.ant-tag-green-inverse{color:#fff;background:#3ea00e;border-color:#3ea00e}.ant-tag-blue{color:#0052cc;background:#e6f7ff;border-color:#8cc6ff}.ant-tag-blue-inverse{color:#fff;background:#0052cc;border-color:#0052cc}.ant-tag-geekblue{color:#2f54eb;background:#f0f5ff;border-color:#adc6ff}.ant-tag-geekblue-inverse{color:#fff;background:#2f54eb;border-color:#2f54eb}.ant-tag-purple{color:#6812ca;background:#f4e5ff;border-color:#c28bf9}.ant-tag-purple-inverse{color:#fff;background:#6812ca;border-color:#6812ca}.ant-tag-success{color:#3ea00e;background:#f2ffe0;border-color:#adf269}.ant-tag-processing{color:#0052cc;background:#e6f7ff;border-color:#8cc6ff}.ant-tag-error{color:#ca1628;background:#fff0f0;border-color:#fc9c9c}.ant-tag-warning{color:#cb6b0b;background:#fff4e0;border-color:#fec57c}.ant-tag>.anticon+span,.ant-tag>span+.anticon{margin-left:7px}.ant-tag-rtl{margin-right:0;margin-left:8px;direction:rtl;text-align:right}.ant-tag-rtl.ant-tag .anticon-close{margin-right:3px;margin-left:0}.ant-tag-rtl.ant-tag>.anticon+span,.ant-tag-rtl.ant-tag>span+.anticon{margin-right:7px;margin-left:0}.ant-timeline{box-sizing:border-box;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;font-feature-settings:"tnum";margin:0;padding:0;list-style:none}.ant-timeline-item{position:relative;margin:0;padding-bottom:20px;font-size:14px;list-style:none}.ant-timeline-item-tail{position:absolute;top:10px;left:4px;height:calc(100% - 10px);border-left:2px solid #f0f0f0}.ant-timeline-item-pending .ant-timeline-item-head{font-size:12px;background-color:transparent}.ant-timeline-item-pending .ant-timeline-item-tail{display:none}.ant-timeline-item-head{position:absolute;width:10px;height:10px;background-color:#fff;border:2px solid transparent;border-radius:100px}.ant-timeline-item-head-blue{color:#0052d9;border-color:#0052d9}.ant-timeline-item-head-red{color:#e34d59;border-color:#e34d59}.ant-timeline-item-head-green{color:#00a870;border-color:#00a870}.ant-timeline-item-head-gray{color:#00000040;border-color:#00000040}.ant-timeline-item-head-custom{position:absolute;top:5.5px;left:5px;width:auto;height:auto;margin-top:0;padding:3px 1px;line-height:1;text-align:center;border:0;border-radius:0;transform:translate(-50%,-50%)}.ant-timeline-item-content{position:relative;top:-7.001px;margin:0 0 0 26px;word-break:break-word}.ant-timeline-item-last>.ant-timeline-item-tail{display:none}.ant-timeline-item-last>.ant-timeline-item-content{min-height:48px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-tail,.ant-timeline.ant-timeline-right .ant-timeline-item-tail,.ant-timeline.ant-timeline-label .ant-timeline-item-tail,.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-head,.ant-timeline.ant-timeline-label .ant-timeline-item-head,.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-label .ant-timeline-item-head-custom{left:50%}.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-head,.ant-timeline.ant-timeline-label .ant-timeline-item-head{margin-left:-4px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom,.ant-timeline.ant-timeline-label .ant-timeline-item-head-custom{margin-left:1px}.ant-timeline.ant-timeline-alternate .ant-timeline-item-left .ant-timeline-item-content,.ant-timeline.ant-timeline-right .ant-timeline-item-left .ant-timeline-item-content,.ant-timeline.ant-timeline-label .ant-timeline-item-left .ant-timeline-item-content{left:calc(50% - 4px);width:calc(50% - 14px);text-align:left}.ant-timeline.ant-timeline-alternate .ant-timeline-item-right .ant-timeline-item-content,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content,.ant-timeline.ant-timeline-label .ant-timeline-item-right .ant-timeline-item-content{width:calc(50% - 12px);margin:0;text-align:right}.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-tail,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head,.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head-custom{left:calc(100% - 6px)}.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content{width:calc(100% - 18px)}.ant-timeline.ant-timeline-pending .ant-timeline-item-last .ant-timeline-item-tail{display:block;height:calc(100% - 14px);border-left:2px dotted #f0f0f0}.ant-timeline.ant-timeline-reverse .ant-timeline-item-last .ant-timeline-item-tail{display:none}.ant-timeline.ant-timeline-reverse .ant-timeline-item-pending .ant-timeline-item-tail{top:15px;display:block;height:calc(100% - 15px);border-left:2px dotted #f0f0f0}.ant-timeline.ant-timeline-reverse .ant-timeline-item-pending .ant-timeline-item-content{min-height:48px}.ant-timeline.ant-timeline-label .ant-timeline-item-label{position:absolute;top:-7.001px;width:calc(50% - 12px);text-align:right}.ant-timeline.ant-timeline-label .ant-timeline-item-right .ant-timeline-item-label{left:calc(50% + 14px);width:calc(50% - 14px);text-align:left}.ant-timeline-rtl{direction:rtl}.ant-timeline-rtl .ant-timeline-item-tail{right:4px;left:auto;border-right:2px solid #f0f0f0;border-left:none}.ant-timeline-rtl .ant-timeline-item-head-custom{right:5px;left:auto;transform:translate(50%,-50%)}.ant-timeline-rtl .ant-timeline-item-content{margin:0 18px 0 0}.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-tail,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-tail,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-tail,.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-head-custom{right:50%;left:auto}.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-head{margin-right:-4px;margin-left:0}.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-head-custom,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-head-custom,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-head-custom{margin-right:1px;margin-left:0}.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-left .ant-timeline-item-content,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-left .ant-timeline-item-content,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-left .ant-timeline-item-content{right:calc(50% - 4px);left:auto;text-align:right}.ant-timeline-rtl.ant-timeline.ant-timeline-alternate .ant-timeline-item-right .ant-timeline-item-content,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content,.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-right .ant-timeline-item-content{text-align:left}.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-tail,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head,.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-head-custom{right:0;left:auto}.ant-timeline-rtl.ant-timeline.ant-timeline-right .ant-timeline-item-right .ant-timeline-item-content{width:100%;margin-right:18px;text-align:right}.ant-timeline-rtl.ant-timeline.ant-timeline-pending .ant-timeline-item-last .ant-timeline-item-tail,.ant-timeline-rtl.ant-timeline.ant-timeline-reverse .ant-timeline-item-pending .ant-timeline-item-tail{border-right:2px dotted #f0f0f0;border-left:none}.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-label{text-align:left}.ant-timeline-rtl.ant-timeline.ant-timeline-label .ant-timeline-item-right .ant-timeline-item-label{right:calc(50% + 14px);text-align:right}.ant-tooltip{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;z-index:1060;display:block;max-width:250px;visibility:visible}.ant-tooltip-hidden{display:none}.ant-tooltip-placement-top,.ant-tooltip-placement-topLeft,.ant-tooltip-placement-topRight{padding-bottom:8px}.ant-tooltip-placement-right,.ant-tooltip-placement-rightTop,.ant-tooltip-placement-rightBottom{padding-left:8px}.ant-tooltip-placement-bottom,.ant-tooltip-placement-bottomLeft,.ant-tooltip-placement-bottomRight{padding-top:8px}.ant-tooltip-placement-left,.ant-tooltip-placement-leftTop,.ant-tooltip-placement-leftBottom{padding-right:8px}.ant-tooltip-inner{min-width:30px;min-height:32px;padding:8px 10px;color:#000a29e6;text-align:left;text-decoration:none;word-wrap:break-word;background-color:#fff;border-radius:3px;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d}.ant-tooltip-arrow{position:absolute;display:block;width:13.07106781px;height:13.07106781px;overflow:hidden;background:transparent;pointer-events:none}.ant-tooltip-arrow-content{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:5px;height:5px;margin:auto;background-color:#fff;content:"";pointer-events:auto}.ant-tooltip-placement-top .ant-tooltip-arrow,.ant-tooltip-placement-topLeft .ant-tooltip-arrow,.ant-tooltip-placement-topRight .ant-tooltip-arrow{bottom:-4.07106781px}.ant-tooltip-placement-top .ant-tooltip-arrow-content,.ant-tooltip-placement-topLeft .ant-tooltip-arrow-content,.ant-tooltip-placement-topRight .ant-tooltip-arrow-content{box-shadow:3px 3px 7px #00000012;transform:translateY(-6.53553391px) rotate(45deg)}.ant-tooltip-placement-top .ant-tooltip-arrow{left:50%;transform:translate(-50%)}.ant-tooltip-placement-topLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-topRight .ant-tooltip-arrow{right:13px}.ant-tooltip-placement-right .ant-tooltip-arrow,.ant-tooltip-placement-rightTop .ant-tooltip-arrow,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{left:-4.07106781px}.ant-tooltip-placement-right .ant-tooltip-arrow-content,.ant-tooltip-placement-rightTop .ant-tooltip-arrow-content,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow-content{box-shadow:-3px 3px 7px #00000012;transform:translate(6.53553391px) rotate(45deg)}.ant-tooltip-placement-right .ant-tooltip-arrow{top:50%;transform:translateY(-50%)}.ant-tooltip-placement-rightTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-left .ant-tooltip-arrow,.ant-tooltip-placement-leftTop .ant-tooltip-arrow,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{right:-4.07106781px}.ant-tooltip-placement-left .ant-tooltip-arrow-content,.ant-tooltip-placement-leftTop .ant-tooltip-arrow-content,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow-content{box-shadow:3px -3px 7px #00000012;transform:translate(-6.53553391px) rotate(45deg)}.ant-tooltip-placement-left .ant-tooltip-arrow{top:50%;transform:translateY(-50%)}.ant-tooltip-placement-leftTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-bottom .ant-tooltip-arrow,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{top:-4.07106781px}.ant-tooltip-placement-bottom .ant-tooltip-arrow-content,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow-content,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow-content{box-shadow:-3px -3px 7px #00000012;transform:translateY(6.53553391px) rotate(45deg)}.ant-tooltip-placement-bottom .ant-tooltip-arrow{left:50%;transform:translate(-50%)}.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{right:13px}.ant-tooltip-pink .ant-tooltip-inner,.ant-tooltip-pink .ant-tooltip-arrow-content,.ant-tooltip-magenta .ant-tooltip-inner,.ant-tooltip-magenta .ant-tooltip-arrow-content{background-color:#eb2f96}.ant-tooltip-red .ant-tooltip-inner,.ant-tooltip-red .ant-tooltip-arrow-content{background-color:#ca1628}.ant-tooltip-volcano .ant-tooltip-inner,.ant-tooltip-volcano .ant-tooltip-arrow-content{background-color:#fa541c}.ant-tooltip-orange .ant-tooltip-inner,.ant-tooltip-orange .ant-tooltip-arrow-content{background-color:#cb6b0b}.ant-tooltip-yellow .ant-tooltip-inner,.ant-tooltip-yellow .ant-tooltip-arrow-content{background-color:#ce9c09}.ant-tooltip-gold .ant-tooltip-inner,.ant-tooltip-gold .ant-tooltip-arrow-content{background-color:#faad14}.ant-tooltip-cyan .ant-tooltip-inner,.ant-tooltip-cyan .ant-tooltip-arrow-content{background-color:#0ba4bc}.ant-tooltip-lime .ant-tooltip-inner,.ant-tooltip-lime .ant-tooltip-arrow-content{background-color:#a0d911}.ant-tooltip-green .ant-tooltip-inner,.ant-tooltip-green .ant-tooltip-arrow-content{background-color:#3ea00e}.ant-tooltip-blue .ant-tooltip-inner,.ant-tooltip-blue .ant-tooltip-arrow-content{background-color:#0052cc}.ant-tooltip-geekblue .ant-tooltip-inner,.ant-tooltip-geekblue .ant-tooltip-arrow-content{background-color:#2f54eb}.ant-tooltip-purple .ant-tooltip-inner,.ant-tooltip-purple .ant-tooltip-arrow-content{background-color:#6812ca}.ant-tooltip-rtl{direction:rtl}.ant-tooltip-rtl .ant-tooltip-inner{text-align:right}.ant-transfer-customize-list{display:flex}.ant-transfer-customize-list .ant-transfer-operation{flex:none;align-self:center}.ant-transfer-customize-list .ant-transfer-list{flex:auto;width:auto;height:auto;min-height:200px}.ant-transfer-customize-list .ant-transfer-list-body-with-search{padding-top:0}.ant-transfer-customize-list .ant-transfer-list-body-search-wrapper{position:relative;padding-bottom:0}.ant-transfer-customize-list .ant-transfer-list-body-customize-wrapper{padding:12px}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small{border:0;border-radius:0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small>.ant-table-content>.ant-table-body>table>.ant-table-thead>tr>th{background:#fff}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small>.ant-table-content .ant-table-row:last-child td{border-bottom:1px solid #f0f0f0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-small .ant-table-body{margin:0}.ant-transfer-customize-list .ant-table-wrapper .ant-table-pagination.ant-pagination{margin:16px 0 4px}.ant-transfer-customize-list .ant-input[disabled]{background-color:transparent}.ant-transfer{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative}.ant-transfer-disabled .ant-transfer-list{background:#f5f5f5}.ant-transfer-list{position:relative;display:inline-block;width:180px;height:200px;padding-top:40px;vertical-align:middle;border:1px solid #d9d9d9;border-radius:3px}.ant-transfer-list-with-footer{padding-bottom:34px}.ant-transfer-list-search{padding-right:24px;padding-left:8px}.ant-transfer-list-search-action{position:absolute;top:12px;right:12px;bottom:12px;width:28px;color:#00000040;line-height:32px;text-align:center}.ant-transfer-list-search-action .anticon{color:#00000040;transition:all .3s}.ant-transfer-list-search-action .anticon:hover{color:#000a2999}span.ant-transfer-list-search-action{pointer-events:none}.ant-transfer-list-header{position:absolute;top:0;left:0;width:100%;padding:8px 8px 9px;overflow:hidden;color:#000a29e6;background:#fff;border-bottom:1px solid #f0f0f0;border-radius:3px 3px 0 0}.ant-transfer-list-header-title{position:absolute;right:12px}.ant-transfer-list-header .ant-checkbox-wrapper+span{padding-left:8px}.ant-transfer-list-body{position:relative;height:100%;font-size:14px}.ant-transfer-list-body-search-wrapper{position:absolute;top:0;left:0;width:100%;padding:12px}.ant-transfer-list-body-with-search{padding-top:56px}.ant-transfer-list-content{height:100%;margin:0;padding:0;overflow:auto;list-style:none}.ant-transfer-list-content-item{min-height:32px;padding:6px 8px;overflow:hidden;line-height:20px;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-transfer-list-content-item>span{padding-right:0}.ant-transfer-list-content-item-text{padding-left:8px}.ant-transfer-list-content-item:not(.ant-transfer-list-content-item-disabled):hover{background-color:#f3f3f3;cursor:pointer}.ant-transfer-list-content-item-checked{background-color:#e0ebff}.ant-transfer-list-content-item-disabled{color:#00000040;cursor:not-allowed}.ant-transfer-list-body-not-found{position:absolute;top:50%;width:100%;padding-top:0;color:#00000040;text-align:center;transform:translateY(-50%)}.ant-transfer-list-body-with-search .ant-transfer-list-body-not-found{margin-top:16px}.ant-transfer-list-footer{position:absolute;bottom:0;left:0;width:100%;border-top:1px solid #f0f0f0;border-radius:0 0 3px 3px}.ant-transfer-operation{display:inline-block;margin:0 8px;overflow:hidden;vertical-align:middle}.ant-transfer-operation .ant-btn{display:block}.ant-transfer-operation .ant-btn:first-child{margin-bottom:4px}.ant-transfer-operation .ant-btn .anticon{font-size:12px}.ant-transfer .ant-empty-image{max-height:-2px}.ant-transfer-rtl{direction:rtl}.ant-transfer-rtl .ant-transfer-list-search{padding-right:8px;padding-left:24px}.ant-transfer-rtl .ant-transfer-list-search-action{right:auto;left:12px}.ant-transfer-rtl .ant-transfer-list-header{right:0;left:auto}.ant-transfer-rtl .ant-transfer-list-header-title{right:auto;left:12px}.ant-transfer-rtl .ant-transfer-list-header .ant-checkbox-wrapper+span{padding-right:8px;padding-left:0}.ant-transfer-rtl .ant-transfer-list-body-search-wrapper{right:0;left:auto}.ant-transfer-rtl .ant-transfer-list-content-item>span{padding-left:0}.ant-transfer-rtl .ant-transfer-list-content-item-text{padding-right:8px;padding-left:0}.ant-transfer-rtl .ant-transfer-list-footer{right:0;left:auto}.ant-tree.ant-tree-directory .ant-tree-treenode{position:relative}.ant-tree.ant-tree-directory .ant-tree-treenode:before{position:absolute;top:0;right:0;bottom:4px;left:0;transition:background-color .3s;content:"";pointer-events:none}.ant-tree.ant-tree-directory .ant-tree-treenode:hover:before{background:#f3f3f3}.ant-tree.ant-tree-directory .ant-tree-treenode>*{z-index:1}.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-switcher{transition:color .3s}.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper{border-radius:0;user-select:none}.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper:hover{background:transparent}.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper.ant-tree-node-selected{color:#fff;background:transparent}.ant-tree.ant-tree-directory .ant-tree-treenode-selected:hover:before,.ant-tree.ant-tree-directory .ant-tree-treenode-selected:before{background:#0052d9}.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher{color:#fff}.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper{color:#fff;background:transparent}.ant-tree-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-inner,.ant-tree-checkbox:hover .ant-tree-checkbox-inner,.ant-tree-checkbox-input:focus+.ant-tree-checkbox-inner{border-color:#0052d9}.ant-tree-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #0052d9;border-radius:3px;visibility:hidden;animation:antCheckboxEffect .36s ease-in-out;animation-fill-mode:backwards;content:""}.ant-tree-checkbox:hover:after,.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox:after{visibility:visible}.ant-tree-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;direction:ltr;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;border-collapse:separate}.ant-tree-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5px;height:8px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:" "}.ant-tree-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after{position:absolute;display:table;border:2px solid #0052d9;border-top:0;border-left:0;transform:rotate(45deg) scale(1.2) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:" "}.ant-tree-checkbox-checked .ant-tree-checkbox-inner{border-color:#0052d9}.ant-tree-checkbox-disabled{cursor:not-allowed}.ant-tree-checkbox-disabled.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after{border-color:#00000040;animation-name:none}.ant-tree-checkbox-disabled .ant-tree-checkbox-input{cursor:not-allowed}.ant-tree-checkbox-disabled .ant-tree-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;animation-name:none}.ant-tree-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-tree-checkbox-disabled:hover:after,.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-disabled:after{visibility:hidden}.ant-tree-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block;line-height:unset;cursor:pointer}.ant-tree-checkbox-wrapper.ant-tree-checkbox-wrapper-disabled{cursor:not-allowed}.ant-tree-checkbox-wrapper+.ant-tree-checkbox-wrapper{margin-left:8px}.ant-tree-checkbox+span{padding-right:8px;padding-left:8px}.ant-tree-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block}.ant-tree-checkbox-group-item{display:inline-block;margin-right:8px}.ant-tree-checkbox-group-item:last-child{margin-right:0}.ant-tree-checkbox-group-item+.ant-tree-checkbox-group-item{margin-left:0}.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner:after{top:50%;left:50%;width:8px;height:3px;background-color:#0052d9;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;transition:none;content:" "}.ant-tree-checkbox-indeterminate.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-tree-checkbox-rtl{direction:rtl}.ant-tree-checkbox-group-rtl .ant-tree-checkbox-group-item{margin-right:0;margin-left:8px}.ant-tree-checkbox-group-rtl .ant-tree-checkbox-group-item:last-child{margin-left:0!important}.ant-tree-checkbox-group-rtl .ant-tree-checkbox-group-item+.ant-tree-checkbox-group-item{margin-left:8px}.ant-tree{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background:#fff;border-radius:3px;transition:background-color .3s}.ant-tree-focused:not(:hover):not(.ant-tree-active-focused){background:#e6f4ff}.ant-tree-list-holder-inner{align-items:flex-start}.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner{align-items:stretch}.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner .ant-tree-node-content-wrapper{flex:auto}.ant-tree .ant-tree-treenode{display:flex;align-items:flex-start;padding:0 0 4px;outline:none}.ant-tree .ant-tree-treenode-disabled .ant-tree-node-content-wrapper{color:#00000040;cursor:not-allowed}.ant-tree .ant-tree-treenode-disabled .ant-tree-node-content-wrapper:hover{background:transparent}.ant-tree .ant-tree-treenode-active .ant-tree-node-content-wrapper{background:#f3f3f3}.ant-tree-indent{align-self:stretch;white-space:nowrap;user-select:none}.ant-tree-indent-unit{display:inline-block;width:24px}.ant-tree .ant-tree-switcher{flex:none;width:24px;height:24px;margin:0;line-height:24px;text-align:center;cursor:pointer}.ant-tree .ant-tree-switcher .ant-tree-switcher-icon,.ant-tree .ant-tree-switcher .ant-select-tree-switcher-icon{font-size:10px;display:inline-block;font-weight:700}.ant-tree .ant-tree-switcher .ant-tree-switcher-icon svg,.ant-tree .ant-tree-switcher .ant-select-tree-switcher-icon svg{transition:transform .3s}.ant-tree .ant-tree-switcher-noop{cursor:default}.ant-tree .ant-tree-switcher_close .ant-tree-switcher-icon svg{transform:rotate(-90deg)}.ant-tree .ant-tree-switcher-loading-icon{color:#0052d9}.ant-tree .ant-tree-checkbox{top:initial;margin:4px 8px 0 0}.ant-tree .ant-tree-node-content-wrapper{min-height:24px;margin:0;padding:0 4px;color:inherit;line-height:24px;background:transparent;border-radius:3px;cursor:pointer;transition:all .3s}.ant-tree .ant-tree-node-content-wrapper:hover{background-color:#f3f3f3}.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected{background-color:#a3d3ff}.ant-tree .ant-tree-node-content-wrapper .ant-tree-iconEle{display:inline-block;width:24px;height:24px;line-height:24px;text-align:center;vertical-align:top}.ant-tree .ant-tree-node-content-wrapper .ant-tree-iconEle:empty{display:none}.ant-tree-node-content-wrapper[draggable=true]{line-height:20px;border-top:2px transparent solid;border-bottom:2px transparent solid;user-select:none}.ant-tree .ant-tree-treenode.drag-over>[draggable]{color:#fff;background-color:#0052d9;opacity:.8}.ant-tree .ant-tree-treenode.drag-over-gap-top>[draggable]{border-top-color:#0052d9}.ant-tree .ant-tree-treenode.drag-over-gap-bottom>[draggable]{border-bottom-color:#0052d9}.ant-tree-show-line .ant-tree-indent-unit{position:relative;height:100%}.ant-tree-show-line .ant-tree-indent-unit:before{position:absolute;top:calc(100% - 4px);right:-12px;bottom:-28px;border-right:1px solid #d9d9d9;content:""}.ant-tree-show-line .ant-tree-indent-unit-end:before{display:none}.ant-tree-show-line .ant-tree-treenode-motion:not(.ant-motion-collapse-leave):not(.ant-motion-collapse-appear-active) .ant-tree-indent-unit:before{display:none}.ant-tree-show-line .ant-tree-switcher{z-index:1;background:#fff}.ant-tree-rtl,.ant-tree .ant-tree-treenode-rtl{direction:rtl}.ant-tree-rtl.ant-tree .ant-tree-switcher_close .ant-tree-switcher-icon svg{transform:rotate(90deg)}.ant-tree-rtl.ant-tree-show-line .ant-tree-indent-unit:before{right:auto;left:-12px;border-right:none;border-left:1px solid #d9d9d9}.ant-select-tree-checkbox{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;top:-.09em;display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;outline:none;cursor:pointer}.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox-inner,.ant-select-tree-checkbox:hover .ant-select-tree-checkbox-inner,.ant-select-tree-checkbox-input:focus+.ant-select-tree-checkbox-inner{border-color:#0052d9}.ant-select-tree-checkbox-checked:after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #0052d9;border-radius:3px;visibility:hidden;animation:antCheckboxEffect .36s ease-in-out;animation-fill-mode:backwards;content:""}.ant-select-tree-checkbox:hover:after,.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox:after{visibility:visible}.ant-select-tree-checkbox-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;direction:ltr;background-color:#fff;border:1px solid #d9d9d9;border-radius:3px;border-collapse:separate}.ant-select-tree-checkbox-inner:after{position:absolute;top:50%;left:22%;display:table;width:5px;height:8px;border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg) scale(0) translate(-50%,-50%);opacity:0;transition:all .1s cubic-bezier(.71,-.46,.88,.6),opacity .1s;content:" "}.ant-select-tree-checkbox-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;cursor:pointer;opacity:0}.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner:after{position:absolute;display:table;border:2px solid #0052d9;border-top:0;border-left:0;transform:rotate(45deg) scale(1.2) translate(-50%,-50%);opacity:1;transition:all .2s cubic-bezier(.12,.4,.29,1.46) .1s;content:" "}.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner{border-color:#0052d9}.ant-select-tree-checkbox-disabled{cursor:not-allowed}.ant-select-tree-checkbox-disabled.ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner:after{border-color:#00000040;animation-name:none}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-input{cursor:not-allowed}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner{background-color:#f5f5f5;border-color:#d9d9d9!important}.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner:after{border-color:#f5f5f5;border-collapse:separate;animation-name:none}.ant-select-tree-checkbox-disabled+span{color:#00000040;cursor:not-allowed}.ant-select-tree-checkbox-disabled:hover:after,.ant-select-tree-checkbox-wrapper:hover .ant-select-tree-checkbox-disabled:after{visibility:hidden}.ant-select-tree-checkbox-wrapper{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block;line-height:unset;cursor:pointer}.ant-select-tree-checkbox-wrapper.ant-select-tree-checkbox-wrapper-disabled{cursor:not-allowed}.ant-select-tree-checkbox-wrapper+.ant-select-tree-checkbox-wrapper{margin-left:8px}.ant-select-tree-checkbox+span{padding-right:8px;padding-left:8px}.ant-select-tree-checkbox-group{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";display:inline-block}.ant-select-tree-checkbox-group-item{display:inline-block;margin-right:8px}.ant-select-tree-checkbox-group-item:last-child{margin-right:0}.ant-select-tree-checkbox-group-item+.ant-select-tree-checkbox-group-item{margin-left:0}.ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner{background-color:#fff;border-color:#d9d9d9}.ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner:after{top:50%;left:50%;width:8px;height:3px;background-color:#0052d9;border:0;transform:translate(-50%,-50%) scale(1);opacity:1;transition:none;content:" "}.ant-select-tree-checkbox-indeterminate.ant-select-tree-checkbox-disabled .ant-select-tree-checkbox-inner:after{background-color:#00000040;border-color:#00000040}.ant-select-tree-checkbox-rtl{direction:rtl}.ant-select-tree-checkbox-group-rtl .ant-select-tree-checkbox-group-item{margin-right:0;margin-left:8px}.ant-select-tree-checkbox-group-rtl .ant-select-tree-checkbox-group-item:last-child{margin-left:0!important}.ant-select-tree-checkbox-group-rtl .ant-select-tree-checkbox-group-item+.ant-select-tree-checkbox-group-item{margin-left:8px}.ant-tree-select-dropdown{padding:8px 4px 0}.ant-tree-select-dropdown-rtl{direction:rtl}.ant-tree-select-dropdown .ant-select-tree{border-radius:0}.ant-tree-select-dropdown .ant-select-tree-list-holder-inner{align-items:stretch}.ant-tree-select-dropdown .ant-select-tree-list-holder-inner .ant-select-tree-treenode{padding-bottom:8px}.ant-tree-select-dropdown .ant-select-tree-list-holder-inner .ant-select-tree-treenode .ant-select-tree-node-content-wrapper{flex:auto}.ant-select-tree{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background:#fff;border-radius:3px;transition:background-color .3s}.ant-select-tree-focused:not(:hover):not(.ant-select-tree-active-focused){background:#e6f4ff}.ant-select-tree-list-holder-inner{align-items:flex-start}.ant-select-tree.ant-select-tree-block-node .ant-select-tree-list-holder-inner{align-items:stretch}.ant-select-tree.ant-select-tree-block-node .ant-select-tree-list-holder-inner .ant-select-tree-node-content-wrapper{flex:auto}.ant-select-tree .ant-select-tree-treenode{display:flex;align-items:flex-start;padding:0 0 4px;outline:none}.ant-select-tree .ant-select-tree-treenode-disabled .ant-select-tree-node-content-wrapper{color:#00000040;cursor:not-allowed}.ant-select-tree .ant-select-tree-treenode-disabled .ant-select-tree-node-content-wrapper:hover{background:transparent}.ant-select-tree .ant-select-tree-treenode-active .ant-select-tree-node-content-wrapper{background:#f3f3f3}.ant-select-tree-indent{align-self:stretch;white-space:nowrap;user-select:none}.ant-select-tree-indent-unit{display:inline-block;width:24px}.ant-select-tree .ant-select-tree-switcher{flex:none;width:24px;height:24px;margin:0;line-height:24px;text-align:center;cursor:pointer}.ant-select-tree .ant-select-tree-switcher .ant-tree-switcher-icon,.ant-select-tree .ant-select-tree-switcher .ant-select-tree-switcher-icon{font-size:10px;display:inline-block;font-weight:700}.ant-select-tree .ant-select-tree-switcher .ant-tree-switcher-icon svg,.ant-select-tree .ant-select-tree-switcher .ant-select-tree-switcher-icon svg{transition:transform .3s}.ant-select-tree .ant-select-tree-switcher-noop{cursor:default}.ant-select-tree .ant-select-tree-switcher_close .ant-select-tree-switcher-icon svg{transform:rotate(-90deg)}.ant-select-tree .ant-select-tree-switcher-loading-icon{color:#0052d9}.ant-select-tree .ant-select-tree-checkbox{top:initial;margin:4px 8px 0 0}.ant-select-tree .ant-select-tree-node-content-wrapper{min-height:24px;margin:0;padding:0 4px;color:inherit;line-height:24px;background:transparent;border-radius:3px;cursor:pointer;transition:all .3s}.ant-select-tree .ant-select-tree-node-content-wrapper:hover{background-color:#f3f3f3}.ant-select-tree .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected{background-color:#a3d3ff}.ant-select-tree .ant-select-tree-node-content-wrapper .ant-select-tree-iconEle{display:inline-block;width:24px;height:24px;line-height:24px;text-align:center;vertical-align:top}.ant-select-tree .ant-select-tree-node-content-wrapper .ant-select-tree-iconEle:empty{display:none}.ant-select-tree-node-content-wrapper[draggable=true]{line-height:20px;border-top:2px transparent solid;border-bottom:2px transparent solid;user-select:none}.ant-select-tree .ant-select-tree-treenode.drag-over>[draggable]{color:#fff;background-color:#0052d9;opacity:.8}.ant-select-tree .ant-select-tree-treenode.drag-over-gap-top>[draggable]{border-top-color:#0052d9}.ant-select-tree .ant-select-tree-treenode.drag-over-gap-bottom>[draggable]{border-bottom-color:#0052d9}.ant-select-tree-show-line .ant-select-tree-indent-unit{position:relative;height:100%}.ant-select-tree-show-line .ant-select-tree-indent-unit:before{position:absolute;top:calc(100% - 4px);right:-12px;bottom:-28px;border-right:1px solid #d9d9d9;content:""}.ant-select-tree-show-line .ant-select-tree-indent-unit-end:before{display:none}.ant-select-tree-show-line .ant-select-tree-treenode-motion:not(.ant-motion-collapse-leave):not(.ant-motion-collapse-appear-active) .ant-select-tree-indent-unit:before{display:none}.ant-select-tree-show-line .ant-select-tree-switcher{z-index:1;background:#fff}.ant-tree-select-dropdown-rtl .ant-select-tree .ant-select-tree-switcher_close .ant-select-tree-switcher-icon svg{transform:rotate(90deg)}.ant-typography{color:#000a29e6}.ant-typography.ant-typography-secondary{color:#000a2999}.ant-typography.ant-typography-warning{color:#f9e0c7}.ant-typography.ant-typography-danger{color:#e34d59}.ant-typography.ant-typography-disabled{color:#00000040;cursor:not-allowed;user-select:none}div.ant-typography,.ant-typography p{margin-bottom:1em}h1.ant-typography,.ant-typography h1{margin-bottom:.5em;color:#000a29e6;font-weight:600;font-size:38px;line-height:1.23}h2.ant-typography,.ant-typography h2{margin-bottom:.5em;color:#000a29e6;font-weight:600;font-size:30px;line-height:1.35}h3.ant-typography,.ant-typography h3{margin-bottom:.5em;color:#000a29e6;font-weight:600;font-size:24px;line-height:1.35}h4.ant-typography,.ant-typography h4{margin-bottom:.5em;color:#000a29e6;font-weight:600;font-size:20px;line-height:1.4}.ant-typography+h1.ant-typography,.ant-typography+h2.ant-typography,.ant-typography+h3.ant-typography,.ant-typography+h4.ant-typography{margin-top:1.2em}.ant-typography div+h1,.ant-typography ul+h1,.ant-typography li+h1,.ant-typography p+h1,.ant-typography h1+h1,.ant-typography h2+h1,.ant-typography h3+h1,.ant-typography h4+h1,.ant-typography div+h2,.ant-typography ul+h2,.ant-typography li+h2,.ant-typography p+h2,.ant-typography h1+h2,.ant-typography h2+h2,.ant-typography h3+h2,.ant-typography h4+h2,.ant-typography div+h3,.ant-typography ul+h3,.ant-typography li+h3,.ant-typography p+h3,.ant-typography h1+h3,.ant-typography h2+h3,.ant-typography h3+h3,.ant-typography h4+h3,.ant-typography div+h4,.ant-typography ul+h4,.ant-typography li+h4,.ant-typography p+h4,.ant-typography h1+h4,.ant-typography h2+h4,.ant-typography h3+h4,.ant-typography h4+h4{margin-top:1.2em}span.ant-typography-ellipsis{display:inline-block}.ant-typography a{color:#0052d9;text-decoration:none;outline:none;cursor:pointer;transition:color .3s}.ant-typography a:focus,.ant-typography a:hover{color:#2575e6}.ant-typography a:active{color:#003eb3}.ant-typography a:active,.ant-typography a:hover{text-decoration:none}.ant-typography a[disabled]{color:#00000040;cursor:not-allowed;pointer-events:none}.ant-typography code{margin:0 .2em;padding:.2em .4em .1em;font-size:85%;background:rgba(0,0,0,.06);border:1px solid rgba(0,0,0,.06);border-radius:3px}.ant-typography mark{padding:0;background-color:#ffe58f}.ant-typography u,.ant-typography ins{text-decoration:underline;text-decoration-skip-ink:auto}.ant-typography s,.ant-typography del{text-decoration:line-through}.ant-typography strong{font-weight:600}.ant-typography-expand,.ant-typography-edit,.ant-typography-copy{color:#0052d9;text-decoration:none;outline:none;cursor:pointer;transition:color .3s;margin-left:8px}.ant-typography-expand:focus,.ant-typography-edit:focus,.ant-typography-copy:focus,.ant-typography-expand:hover,.ant-typography-edit:hover,.ant-typography-copy:hover{color:#2575e6}.ant-typography-expand:active,.ant-typography-edit:active,.ant-typography-copy:active{color:#003eb3}.ant-typography-copy-success,.ant-typography-copy-success:hover,.ant-typography-copy-success:focus{color:#00a870}.ant-typography-edit-content{position:relative}div.ant-typography-edit-content{left:-9px;margin-top:-5px;margin-bottom:calc(1em - 6px)}.ant-typography-edit-content-confirm{position:absolute;right:10px;bottom:8px;color:#000a2999;pointer-events:none}.ant-typography-edit-content textarea{-moz-transition:none}.ant-typography ul,.ant-typography ol{margin:0 0 1em;padding:0}.ant-typography ul li,.ant-typography ol li{margin:0 0 0 20px;padding:0 0 0 4px}.ant-typography ul{list-style-type:circle}.ant-typography ul ul{list-style-type:disc}.ant-typography ol{list-style-type:decimal}.ant-typography-ellipsis-single-line{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}span.ant-typography-ellipsis-single-line{vertical-align:bottom}.ant-typography-ellipsis-multiple-line{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ant-typography-rtl{direction:rtl}.ant-typography-rtl .ant-typography-expand,.ant-typography-rtl .ant-typography-edit,.ant-typography-rtl .ant-typography-copy{margin-right:8px;margin-left:0}.ant-typography-rtl .ant-typography-expand{float:left}div.ant-typography-edit-content.ant-typography-rtl{right:-9px;left:auto}.ant-typography-rtl .ant-typography-edit-content-confirm{right:auto;left:10px}.ant-typography-rtl.ant-typography ul li,.ant-typography-rtl.ant-typography ol li{margin:0 20px 0 0;padding:0 4px 0 0}.ant-upload{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";outline:0}.ant-upload p{margin:0}.ant-upload-btn{display:block;width:100%;outline:none}.ant-upload input[type=file]{cursor:pointer}.ant-upload.ant-upload-select{display:inline-block}.ant-upload.ant-upload-disabled{cursor:not-allowed}.ant-upload.ant-upload-select-picture-card{display:table;float:left;width:104px;height:104px;margin-right:8px;margin-bottom:8px;text-align:center;vertical-align:top;background-color:#f1f2f5;border:1px dashed #d9d9d9;border-radius:3px;cursor:pointer;transition:border-color .3s ease}.ant-upload.ant-upload-select-picture-card>.ant-upload{display:table-cell;width:100%;height:100%;padding:8px;text-align:center;vertical-align:middle}.ant-upload.ant-upload-select-picture-card:hover{border-color:#0052d9}.ant-upload-disabled.ant-upload.ant-upload-select-picture-card:hover{border-color:#d9d9d9}.ant-upload.ant-upload-drag{position:relative;width:100%;height:100%;text-align:center;background:#f1f2f5;border:1px dashed #d9d9d9;border-radius:3px;cursor:pointer;transition:border-color .3s}.ant-upload.ant-upload-drag .ant-upload{padding:16px 0}.ant-upload.ant-upload-drag.ant-upload-drag-hover:not(.ant-upload-disabled){border-color:#003eb3}.ant-upload.ant-upload-drag.ant-upload-disabled{cursor:not-allowed}.ant-upload.ant-upload-drag .ant-upload-btn{display:table;height:100%}.ant-upload.ant-upload-drag .ant-upload-drag-container{display:table-cell;vertical-align:middle}.ant-upload.ant-upload-drag:not(.ant-upload-disabled):hover{border-color:#2575e6}.ant-upload.ant-upload-drag p.ant-upload-drag-icon{margin-bottom:20px}.ant-upload.ant-upload-drag p.ant-upload-drag-icon .anticon{color:#2575e6;font-size:48px}.ant-upload.ant-upload-drag p.ant-upload-text{margin:0 0 4px;color:#000a29e6;font-size:16px}.ant-upload.ant-upload-drag p.ant-upload-hint{color:#000a2999;font-size:14px}.ant-upload.ant-upload-drag .anticon-plus{color:#00000040;font-size:30px;transition:all .3s}.ant-upload.ant-upload-drag .anticon-plus:hover,.ant-upload.ant-upload-drag:hover .anticon-plus{color:#000a2999}.ant-upload-picture-card-wrapper{display:inline-block;width:100%}.ant-upload-picture-card-wrapper:before{display:table;content:""}.ant-upload-picture-card-wrapper:after{display:table;clear:both;content:""}.ant-upload-list{box-sizing:border-box;margin:0;padding:0;color:#000a29e6;font-size:14px;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";line-height:1.5715}.ant-upload-list:before{display:table;content:""}.ant-upload-list:after{display:table;clear:both;content:""}.ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-1{padding-right:14px}.ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-2{padding-right:28px}.ant-upload-list-item{position:relative;height:22.001px;margin-top:8px;font-size:14px}.ant-upload-list-item-name{display:inline-block;width:100%;padding-left:22px;overflow:hidden;line-height:1.5715;white-space:nowrap;text-overflow:ellipsis}.ant-upload-list-item-name-icon-count-1{padding-right:14px}.ant-upload-list-item-card-actions{position:absolute;right:0;opacity:0}.ant-upload-list-item-card-actions.picture{top:25px;line-height:1;opacity:1}.ant-upload-list-item-card-actions .anticon{padding-right:6px;color:#000a2999}.ant-upload-list-item-info{height:100%;padding:0 12px 0 4px;transition:background-color .3s}.ant-upload-list-item-info>span{display:block;width:100%;height:100%}.ant-upload-list-item-info .anticon-loading .anticon,.ant-upload-list-item-info .ant-upload-text-icon .anticon{position:absolute;top:5px;color:#000a2999;font-size:14px}.ant-upload-list-item .anticon-close{display:inline-block;font-size:10px;position:absolute;top:6px;right:4px;color:#000a2999;line-height:0;cursor:pointer;opacity:0;transition:all .3s}.ant-upload-list-item .anticon-close:hover{color:#000a29e6}.ant-upload-list-item:hover .ant-upload-list-item-info{background-color:#f3f3f3}.ant-upload-list-item:hover .anticon-close,.ant-upload-list-item:hover .ant-upload-list-item-card-actions{opacity:1}.ant-upload-list-item-error,.ant-upload-list-item-error .ant-upload-text-icon>.anticon,.ant-upload-list-item-error .ant-upload-list-item-name{color:#e34d59}.ant-upload-list-item-error .ant-upload-list-item-card-actions{opacity:1}.ant-upload-list-item-error .ant-upload-list-item-card-actions .anticon{color:#e34d59}.ant-upload-list-item-progress{position:absolute;bottom:-12px;width:100%;padding-left:26px;font-size:14px;line-height:0}.ant-upload-list-picture .ant-upload-list-item,.ant-upload-list-picture-card .ant-upload-list-item{position:relative;height:66px;padding:8px;border:1px solid #d9d9d9;border-radius:3px}.ant-upload-list-picture .ant-upload-list-item:hover,.ant-upload-list-picture-card .ant-upload-list-item:hover{background:transparent}.ant-upload-list-picture .ant-upload-list-item-error,.ant-upload-list-picture-card .ant-upload-list-item-error{border-color:#e34d59}.ant-upload-list-picture .ant-upload-list-item-info,.ant-upload-list-picture-card .ant-upload-list-item-info{padding:0}.ant-upload-list-picture .ant-upload-list-item:hover .ant-upload-list-item-info,.ant-upload-list-picture-card .ant-upload-list-item:hover .ant-upload-list-item-info{background:transparent}.ant-upload-list-picture .ant-upload-list-item-uploading,.ant-upload-list-picture-card .ant-upload-list-item-uploading{border-style:dashed}.ant-upload-list-picture .ant-upload-list-item-thumbnail,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail{position:absolute;top:8px;left:8px;width:48px;height:48px;line-height:54px;text-align:center;opacity:.8}.ant-upload-list-picture .ant-upload-list-item-thumbnail .anticon,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail .anticon{font-size:26px}.ant-upload-list-picture .ant-upload-list-item-icon,.ant-upload-list-picture-card .ant-upload-list-item-icon{position:absolute;top:50%;left:50%;font-size:26px;transform:translate(-50%,-50%)}.ant-upload-list-picture .ant-upload-list-item-icon .anticon,.ant-upload-list-picture-card .ant-upload-list-item-icon .anticon{font-size:26px}.ant-upload-list-picture .ant-upload-list-item-image,.ant-upload-list-picture-card .ant-upload-list-item-image{max-width:100%}.ant-upload-list-picture .ant-upload-list-item-thumbnail img,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail img{display:block;width:48px;height:48px;overflow:hidden}.ant-upload-list-picture .ant-upload-list-item-name,.ant-upload-list-picture-card .ant-upload-list-item-name{display:inline-block;box-sizing:border-box;max-width:100%;margin:0 0 0 8px;padding-right:8px;padding-left:48px;overflow:hidden;line-height:44px;white-space:nowrap;text-overflow:ellipsis;transition:all .3s}.ant-upload-list-picture .ant-upload-list-item-name-icon-count-1,.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-1{padding-right:18px}.ant-upload-list-picture .ant-upload-list-item-name-icon-count-2,.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-2{padding-right:36px}.ant-upload-list-picture .ant-upload-list-item-uploading .ant-upload-list-item-name,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-name{line-height:28px}.ant-upload-list-picture .ant-upload-list-item-progress,.ant-upload-list-picture-card .ant-upload-list-item-progress{bottom:14px;width:calc(100% - 24px);margin-top:0;padding-left:56px}.ant-upload-list-picture .anticon-close,.ant-upload-list-picture-card .anticon-close{position:absolute;top:8px;right:8px;line-height:1;opacity:1}.ant-upload-list-picture-card.ant-upload-list:after{display:none}.ant-upload-list-picture-card-container,.ant-upload-list-picture-card .ant-upload-list-item{float:left;width:104px;height:104px;margin:0 8px 8px 0}.ant-upload-list-picture-card .ant-upload-list-item-info{position:relative;height:100%;overflow:hidden}.ant-upload-list-picture-card .ant-upload-list-item-info:before{position:absolute;z-index:1;width:100%;height:100%;background-color:#00000080;opacity:0;transition:all .3s;content:" "}.ant-upload-list-picture-card .ant-upload-list-item:hover .ant-upload-list-item-info:before{opacity:1}.ant-upload-list-picture-card .ant-upload-list-item-actions{position:absolute;top:50%;left:50%;z-index:10;white-space:nowrap;transform:translate(-50%,-50%);opacity:0;transition:all .3s}.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-eye,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-download,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-delete{z-index:10;width:16px;margin:0 4px;color:#ffffffd9;font-size:16px;cursor:pointer;transition:all .3s}.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-eye:hover,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-download:hover,.ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-delete:hover{color:#fff}.ant-upload-list-picture-card .ant-upload-list-item-info:hover+.ant-upload-list-item-actions,.ant-upload-list-picture-card .ant-upload-list-item-actions:hover{opacity:1}.ant-upload-list-picture-card .ant-upload-list-item-thumbnail,.ant-upload-list-picture-card .ant-upload-list-item-thumbnail img{position:static;display:block;width:100%;height:100%;object-fit:cover}.ant-upload-list-picture-card .ant-upload-list-item-name{display:none;margin:8px 0 0;padding:0;line-height:1.5715;text-align:center}.ant-upload-list-picture-card .ant-upload-list-item-file+.ant-upload-list-item-name{position:absolute;bottom:10px;display:block}.ant-upload-list-picture-card .ant-upload-list-item-uploading.ant-upload-list-item{background-color:#f1f2f5}.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info{height:auto}.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info:before,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info .anticon-eye,.ant-upload-list-picture-card .ant-upload-list-item-uploading .ant-upload-list-item-info .anticon-delete{display:none}.ant-upload-list-picture-card .ant-upload-list-item-progress{bottom:32px;padding-left:0}.ant-upload-list .ant-upload-success-icon{color:#00a870;font-weight:700}.ant-upload-list .ant-upload-animate-enter,.ant-upload-list .ant-upload-animate-leave,.ant-upload-list .ant-upload-animate-inline-enter,.ant-upload-list .ant-upload-animate-inline-leave{animation-duration:.3s;animation-fill-mode:cubic-bezier(.78,.14,.15,.86)}.ant-upload-list .ant-upload-animate-enter{animation-name:uploadAnimateIn}.ant-upload-list .ant-upload-animate-leave{animation-name:uploadAnimateOut}.ant-upload-list .ant-upload-animate-inline-enter{animation-name:uploadAnimateInlineIn}.ant-upload-list .ant-upload-animate-inline-leave{animation-name:uploadAnimateInlineOut}@keyframes uploadAnimateIn{0%{height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateOut{to{height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateInlineIn{0%{width:0;height:0;margin:0;padding:0;opacity:0}}@keyframes uploadAnimateInlineOut{to{width:0;height:0;margin:0;padding:0;opacity:0}}.ant-upload-rtl{direction:rtl}.ant-upload-rtl.ant-upload.ant-upload-select-picture-card{float:right;margin-right:0;margin-left:8px}.ant-upload-list-rtl{direction:rtl}.ant-upload-list-rtl .ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-1{padding-right:22px;padding-left:14px}.ant-upload-list-rtl .ant-upload-list-item-list-type-text:hover .ant-upload-list-item-name-icon-count-2{padding-right:22px;padding-left:28px}.ant-upload-list-rtl .ant-upload-list-item-name{padding-right:22px;padding-left:0}.ant-upload-list-rtl .ant-upload-list-item-name-icon-count-1{padding-left:14px}.ant-upload-list-rtl .ant-upload-list-item-card-actions{right:auto;left:0}.ant-upload-list-rtl .ant-upload-list-item-card-actions .anticon{padding-right:0;padding-left:5px}.ant-upload-list-rtl .ant-upload-list-item-info{padding:0 4px 0 12px}.ant-upload-list-rtl .ant-upload-list-item .anticon-close{right:auto;left:4px}.ant-upload-list-rtl .ant-upload-list-item-error .ant-upload-list-item-card-actions .anticon{padding-right:0;padding-left:5px}.ant-upload-list-rtl .ant-upload-list-item-progress{padding-right:26px;padding-left:0}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-thumbnail,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-thumbnail{right:8px;left:auto}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-icon,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-icon{right:50%;left:auto;transform:translate(50%,-50%)}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-name,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-name{margin:0 8px 0 0;padding-right:48px;padding-left:8px}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-name-icon-count-1,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-1{padding-right:48px;padding-left:18px}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-name-icon-count-2,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-name-icon-count-2{padding-right:48px;padding-left:36px}.ant-upload-list-rtl.ant-upload-list-picture .ant-upload-list-item-progress,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-progress{padding-right:56px;padding-left:0}.ant-upload-list-rtl.ant-upload-list-picture .anticon-close,.ant-upload-list-rtl.ant-upload-list-picture-card .anticon-close{right:auto;left:8px}.ant-upload-list-rtl .ant-upload-list-picture-card-container,.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item{float:right;margin:0 0 8px 8px}.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-actions{right:50%;left:auto;transform:translate(50%,-50%)}.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-file+.ant-upload-list-item-name{margin:8px 0 0;padding:0}.ant-upload-list-rtl.ant-upload-list-picture-card .ant-upload-list-item-info{padding:0}body{background:#fff;color:#000a29e6} diff --git a/web/packages/shared/tca/component/index.ts b/web/packages/shared/tca/component/index.ts index 715ba6587..2b0e47d96 100644 --- a/web/packages/shared/tca/component/index.ts +++ b/web/packages/shared/tca/component/index.ts @@ -1 +1,2 @@ export { default as NodeStatus } from './node-status'; +export { default as Operation } from './operation'; diff --git a/web/packages/shared/tca/component/operation/index.tsx b/web/packages/shared/tca/component/operation/index.tsx new file mode 100644 index 000000000..7e46bca52 --- /dev/null +++ b/web/packages/shared/tca/component/operation/index.tsx @@ -0,0 +1,139 @@ +import React, { useEffect, useCallback, useState } from 'react'; +import { Table } from 'coding-oa-uikit'; +import { pick } from 'lodash'; + +import Search, { SearchFormField } from '../../../component/search'; +import { Filter as FilterParams } from '../../../util/types'; +import { formatDateTime } from '../../../util'; + +const { Column } = Table; + +/** 配置默认的pager */ +const DEFAULT_PAGER = { + count: 0, + pageStart: 0, + pageSize: 10, +}; + +/** 操作日志数据结构 */ +interface OperationData { + /** ID */ + id: number; + /** 创建人 */ + creator: string; + /** 创建时间 */ + created_time: string; + /** 信息 */ + message: string; + /** 操作类型 */ + action: string +} + +/** 操作日志返回结果数据结构 */ +interface OperationRestfulListData { + results: OperationData[]; + count: number; + next: string; + previous: string +} + +export interface OperationProps { + /** 传入的请求, 传入时需要避免副作用,通常使用useCallback包裹 */ + opRequest: (params: any) => Promise | null; + /** 筛选字段 */ + searchFields?: SearchFormField[]; + /** className */ + className?: string; + /** style */ + style?: React.CSSProperties; +} + +const Operation = ({ opRequest, searchFields, className, style }: OperationProps) => { + /** 筛选参数 */ + const [searchParams, setSearchParams] = useState({ + limit: DEFAULT_PAGER.pageSize, + offset: DEFAULT_PAGER.pageStart, + }); + /** 操作日志数据 */ + const [{ loading, count, dataSource }, setData] = useState<{ + loading: boolean; + count: number; + dataSource: OperationData[]; + }>({ loading: false, count: 0, dataSource: [] }); + + /** 获取操作日志列表数据 */ + const getListData = useCallback((params?: FilterParams) => { + setData(pre => ({ ...pre, loading: true })); + /** 筛选项 */ + const searchParams = { + limit: DEFAULT_PAGER.pageSize, + offset: DEFAULT_PAGER.pageStart, + ...params, + }; + setSearchParams(searchParams); + opRequest(searchParams)?.then(({ count, results }) => { + setData(pre => ({ + ...pre, + count, + dataSource: results, + })); + }) + .finally(() => setData(pre => ({ ...pre, loading: false }))); + }, [opRequest]); + + useEffect(() => { + getListData(); + }, [getListData]); + + /** 筛选回调 */ + const searchCallback = useCallback((params: any) => { + getListData(params); + }, [getListData]); + + /** 翻页回调 */ + const tableChange = useCallback((page: number, pageSize: number = DEFAULT_PAGER.pageSize) => { + getListData({ + ...searchParams, + limit: pageSize, + offset: (page - 1) * pageSize, + }); + }, [getListData, searchParams]); + + return
+ {searchFields && field.name))} callback={searchCallback} />} + `${range[0]} - ${range[1]} 条数据,共 ${total} 条`, + onChange: tableChange, + }}> + + + + formatDateTime(created_time)} + /> +
+
; +}; + +export default Operation; diff --git a/web/packages/shared/tdesign-component/authority/constants.ts b/web/packages/shared/tdesign-component/authority/constants.ts new file mode 100644 index 000000000..e054a0c72 --- /dev/null +++ b/web/packages/shared/tdesign-component/authority/constants.ts @@ -0,0 +1,46 @@ +import { generateOptions } from '@tencent/micro-frontend-shared/util'; + +/** 平台类型 */ +export enum ScmPlatformEnum { + TGIT = 1, + GIT_TENCENT, + CODING, + GITHUB, + GITEE, + GITLAB, + OTHER, +} + +export const SCM_PLATFORM_CHOICES = { + [ScmPlatformEnum.TGIT]: '腾讯工蜂(OA)', + [ScmPlatformEnum.GIT_TENCENT]: '腾讯工蜂', + [ScmPlatformEnum.CODING]: 'Coding', + [ScmPlatformEnum.GITHUB]: 'GitHub', + [ScmPlatformEnum.GITEE]: 'Gitee', + [ScmPlatformEnum.GITLAB]: 'GitLab', + [ScmPlatformEnum.OTHER]: '其它平台', +}; + +export const SCM_PLATFORM_OPTIONS = generateOptions(SCM_PLATFORM_CHOICES, true); + +/** + * 凭证类型 + */ +export const AUTH_TYPE = { + HTTP: 'password', + SSH: 'ssh_token', + OAUTH: 'oauth', +}; + +export const AUTH_TYPE_TXT = { + HTTP: '用户名 + 密码', + SSH: 'SSH', + OAUTH: 'OAuth', +}; + +// 凭证映射,对应 api 返回的字段名 +export const SCM_MAP = { + [AUTH_TYPE.HTTP]: 'scm_account', + [AUTH_TYPE.SSH]: 'scm_ssh', + [AUTH_TYPE.OAUTH]: 'scm_oauth', +}; diff --git a/web/packages/shared/tdesign-component/authority/index.tsx b/web/packages/shared/tdesign-component/authority/index.tsx new file mode 100644 index 000000000..69763cce4 --- /dev/null +++ b/web/packages/shared/tdesign-component/authority/index.tsx @@ -0,0 +1,172 @@ +/** + * 选择认证 + */ +import React, { useState, useEffect } from 'react'; +import { find, isEmpty, filter, get } from 'lodash'; +import { useHistory } from 'react-router-dom'; +import { Button, Form, Select, Tooltip, FormInstanceFunctions } from 'tdesign-react'; +import { AddIcon, RefreshIcon } from 'tdesign-icons-react'; + +import { AUTH_TYPE, AUTH_TYPE_TXT, SCM_MAP, SCM_PLATFORM_CHOICES } from './constants'; + +const { FormItem } = Form; + +const { Option, OptionGroup } = Select; + +export interface RestfulListAPIParams { + results: any[]; + count: number; + next: string; + previous: string +} + +interface AuthorityProps { + name: string; // 对应表单 name + form: FormInstanceFunctions; // form 对象 + label: string | React.ReactNode; // FormItem label + /* 接口顺序:获取ssh凭证,获取用户名密码凭证,获取各平台OAuth授权状态,获取各平台OAuth应用配置状态 **/ + getAuthList: Array<(param?: any) => Promise>; + initAuth?: any; + selectStyle?: any; + placeholder?: string; + required?: boolean; +} + +const Authority = (props: AuthorityProps) => { + const { form, name, label, initAuth, getAuthList, selectStyle = {}, placeholder, required } = props; + const [sshAuthList, setSshAuthList] = useState([]); + const [httpAuthList, setHttpAuthList] = useState([]); + const [oauthAuthList, setOauthAuthList] = useState([]); + const [authLoading, setAuthLoading] = useState(false); + const history = useHistory(); + + const setCurAuth = (sshList = sshAuthList, httpList = httpAuthList) => { + // 设置初始值 + if (initAuth[SCM_MAP[initAuth.auth_type]]?.id) { + form?.setFieldsValue?.({ [name]: `${initAuth.auth_type}#${initAuth[SCM_MAP[initAuth.auth_type]]?.id}` }); + } + + // 确保当前凭证在select数据内 + if ( + initAuth.scm_ssh + && initAuth.auth_type === AUTH_TYPE.SSH + && !find(sshList, { id: initAuth.scm_ssh?.id }) + ) { + setSshAuthList([initAuth.scm_ssh, ...sshList]); + } + if ( + initAuth.scm_account + && initAuth.auth_type === AUTH_TYPE.HTTP + && !find(httpList, { id: initAuth.scm_account?.id }) + ) { + setHttpAuthList([initAuth.scm_account, ...httpList]); + } + }; + + const getAuth = () => { + setAuthLoading(true); + Promise.all([ + getAuthList[0]({ limit: 200 }) + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[1]({ limit: 200 }) + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[2]() + .then(({ results }: RestfulListAPIParams) => results || []), + getAuthList[3]().then(r => r || {}), + ]).then((result: any) => { + const activeOauth = filter( + result[2].map((item: any) => ({ + ...item, + platform_status: get(result[3], item.scm_platform_name, [false]), + })), + 'platform_status', + ); + setSshAuthList(result[0]); + setHttpAuthList(result[1]); + setOauthAuthList(activeOauth); + setAuthLoading(false); + }); + }; + + useEffect(() => { + getAuth(); + }, []); + + useEffect(() => { + if (!isEmpty(initAuth) && !authLoading) { + setCurAuth(); + } + }, [initAuth, authLoading]); + + return ( + + + + +
+ + + + + + +
+
+ ); +}; + +export default Authority; diff --git a/web/packages/shared/tdesign-component/search/index.tsx b/web/packages/shared/tdesign-component/search/index.tsx index 8b2f21977..3f2a0fbd0 100644 --- a/web/packages/shared/tdesign-component/search/index.tsx +++ b/web/packages/shared/tdesign-component/search/index.tsx @@ -31,8 +31,12 @@ export interface SearchFormField extends FilterField { label?: string; /** 表单 placeholder */ placeholder?: string; + /** 表单 加载状态 */ + loading?: boolean; /** select options,仅type为select时生效 */ options?: any[]; + /** select 可选择,仅type为select时生效 */ + filterable?: boolean; /** 表单样式 */ style?: React.CSSProperties; } @@ -100,6 +104,7 @@ const Search = ({ const params = { ...searchParams, [key]: value, + offset: null, }; onRouteHandle(params); callback?.(params); @@ -110,6 +115,7 @@ const Search = ({ ...searchParams, [`${key}_gte`]: range[0], [`${key}_lte`]: range[1], + offset: null, }; onRouteHandle(params); callback?.(params); @@ -119,7 +125,10 @@ const Search = ({ const params: FilterParams = {}; // 将筛选入参清空 Object.keys(searchParams).forEach((key) => { - params[key] = ''; + params[key] = []; + if (key.endsWith('_lte') || key.endsWith('_gte')) { + params[key.substring(0, key.length - 4)] = ''; + } }); onRouteHandle({ ...params, ...defaultValues }); callback?.({ ...params, ...defaultValues }); @@ -138,6 +147,8 @@ const Search = ({ case 'select': return ; @@ -45,11 +49,11 @@ const ScanModal = (props: IProps) => { case 'select': { return ( ); } @@ -64,7 +68,12 @@ const ScanModal = (props: IProps) => { const data = mapValues(formData, item => (item instanceof moment ? moment(item).format('YYYY-MM-DD') : item)); setLoading(true); - createToolScans(repoId, projectId, toolName, pickBy(data, value => value)) + createToolScans( + repoId, + projectId, + toolName, + pickBy(data, value => value), + ) .then(() => { callback(); onReset(); @@ -81,7 +90,7 @@ const ScanModal = (props: IProps) => { return ( { okButtonProps={{ loading, }} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > -
- { - scanParams.map((item: any, index: number) => ( - - {getComponent(item)} - - )) - } + + {scanParams.map((item: any, index: number) => ( + + {getComponent(item)} + + ))}
); diff --git a/web/packages/tca-analysis/src/modules/projects/code-tools/scans.tsx b/web/packages/tca-analysis/src/modules/projects/code-tools/scans.tsx index 29462d0e6..0003936d5 100644 --- a/web/packages/tca-analysis/src/modules/projects/code-tools/scans.tsx +++ b/web/packages/tca-analysis/src/modules/projects/code-tools/scans.tsx @@ -4,7 +4,6 @@ // See LICENSE for details // ============================================================================== - /** * 工具分析详情 */ @@ -19,11 +18,13 @@ import { Button, Table, Avatar } from 'coding-oa-uikit'; import RunningIcon from '@src/components/running-icon'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; - // import { getProjectRouter } from '@src/utils/getRoutePath'; -import { DEFAULT_PAGER } from '@src/common/constants'; -import { getCodeToolDetail, getCodeToolScans, getCodeToolParams } from '@src/services/projects'; - +import { DEFAULT_PAGER } from '@src/constant'; +import { + getCodeToolDetail, + getCodeToolScans, + getCodeToolParams, +} from '@src/services/projects'; import { TOOLS_STATUS } from '../constants'; @@ -60,7 +61,6 @@ const Scans = (props: ScansProps) => { getScansList(); }, [toolName]); - const onChangePageSize = (page: number, pageSize: number) => { getScansList((page - 1) * pageSize, pageSize); }; @@ -69,9 +69,11 @@ const Scans = (props: ScansProps) => { getScansList(DEFAULT_PAGER.pageStart, size); }; - - const getScansList = async (offset = DEFAULT_PAGER.pageStart, limit = DEFAULT_PAGER.pageSize) => { - const res = await getCodeToolScans(projectId, toolName, { offset, limit }) || {}; + const getScansList = async ( + offset = DEFAULT_PAGER.pageStart, + limit = DEFAULT_PAGER.pageSize, + ) => { + const res = (await getCodeToolScans(projectId, toolName, { offset, limit })) || {}; setPager({ pageSize: limit, @@ -82,19 +84,24 @@ const Scans = (props: ScansProps) => { // setList(mockList.results); }; - const getToolStatus = (code: any) => { if (code >= 0 && code <= 99) { return 'success'; - } if (code >= 100 && code <= 299) { + } + if (code >= 100 && code <= 299) { return 'failed'; - } if (code >= 300 && code <= 399) { + } + if (code >= 300 && code <= 399) { return 'aborted'; } return ''; }; - const { display_name: displayName, status, description } = toolDetail.checktool || {}; + const { + display_name: displayName, + status, + description, + } = toolDetail.checktool || {}; return (
@@ -105,7 +112,9 @@ const Scans = (props: ScansProps) => { {TOOLS_STATUS[status]}
- +

工具介绍

{description}

@@ -122,7 +131,7 @@ const Scans = (props: ScansProps) => { } */} `${item.id}${index}`} @@ -136,55 +145,60 @@ const Scans = (props: ScansProps) => { onShowSizeChange, }} > + - time && moment(time, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')} + render={time => time + && moment(time, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss') + } /> time && formatTime(parseInt(time))} + // render={time => time && formatTime(parseInt(time))} /> (code === null ? ( - + ) : ( -
{get(item, 'scan.result_code_msg')}
+
+ {get(item, 'scan.result_code_msg')} +
)) } /> creator && ( - <> - } /> -  {creator} - - )} + <> + } /> +  {creator} + + ) + } /> ( <> - { - item.result_data_url && 下载结果文件 - } - { - item.result_other_url && 下载其他文件 - } + {item.result_data_url && ( + 下载结果文件 + )} + {item.result_other_url && ( + + 下载其他文件 + + )} )} /> @@ -194,7 +208,9 @@ const Scans = (props: ScansProps) => { params={{ repoId, projectId, toolName }} onHide={() => setVisible(false)} scanParams={scanParams} - callback={getScansList} + callback={() => { + getScansList(); + }} /> ); diff --git a/web/packages/tca-analysis/src/modules/projects/code-tools/style.scss b/web/packages/tca-analysis/src/modules/projects/code-tools/style.scss index 8ca3303df..f00290423 100644 --- a/web/packages/tca-analysis/src/modules/projects/code-tools/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/code-tools/style.scss @@ -1,5 +1,5 @@ /* stylelint-disable */ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .tool-common { margin-top: 30px; diff --git a/web/packages/tca-analysis/src/modules/projects/constants.ts b/web/packages/tca-analysis/src/modules/projects/constants.ts index 9b1d816ce..7e25d2717 100644 --- a/web/packages/tca-analysis/src/modules/projects/constants.ts +++ b/web/packages/tca-analysis/src/modules/projects/constants.ts @@ -1,13 +1,5 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - /* eslint-disable */ -import { t } from '@src/i18n/i18next'; - export const ISSUE_STATUS = { 1: '已修复', 2: '无需修复', @@ -308,13 +300,13 @@ export const SCAN_TYPE = { }; export const SCAN_TYPE_TXT = { - INCR: t('增量分析'), - FULL: t('全量分析'), - MR: t('合流任务'), - COV: t('覆盖率'), - EXPAND: t('扩展功能'), - CR_FULL: t('CR 全量分析'), - CR_INCR: t('CR 增量分析'), + INCR: '增量分析', + FULL: '全量分析', + MR: '合流任务', + COV: '覆盖率', + EXPAND: '扩展功能', + CR_FULL: 'CR 全量分析', + CR_INCR: 'CR 增量分析', }; export const SCAN_TYPE_CHOICES = { @@ -332,22 +324,22 @@ export const SCAN_TYPE_CHOICES = { */ export const SEVERITY_OPTIONS = [ { - label: t('致命'), + label: '致命', en_label: 'fatal', value: 1, }, { - label: t('错误'), + label: '错误', en_label: 'error', value: 2, }, { - label: t('警告'), + label: '警告', en_label: 'warning', value: 3, }, { - label: t('提示'), + label: '提示', en_label: 'info', value: 4, }, @@ -361,10 +353,10 @@ export const SEVERITY_TYPE = { }; export const SEVERITY_TYPE_TXT = { - FATAL: t('致命'), - ERROR: t('错误'), - WARNING: t('警告'), - INFO: t('提示'), + FATAL: '致命', + ERROR: '错误', + WARNING: '警告', + INFO: '提示', }; /** @@ -372,14 +364,14 @@ export const SEVERITY_TYPE_TXT = { */ export const CATEGORY_TYPE_TXT = { NULL: '-', - CORRECTNESS: t('功能'), - SECURITY: t('安全'), - PERFORMANCE: t('性能'), - USABILITY: t('可用性'), - ACCESSIBILITY: t('无障碍化'), - I18N: t('国际化'), - CONVENTION: t('代码风格'), - OTHER: t('其他'), + CORRECTNESS: '功能', + SECURITY: '安全', + PERFORMANCE: '性能', + USABILITY: '可用性', + ACCESSIBILITY: '无障碍化', + I18N: '国际化', + CONVENTION: '代码风格', + OTHER: '其他', }; export const CATEGORY_TYPE = { @@ -438,9 +430,9 @@ export const LINT_STATE_TYPE = { }; export const LINT_STATE_TYPE_TXT = { - ACTIVE: t('未处理'), - RESOLVED: t('已处理'), - CLOSED: t('已关闭'), + ACTIVE: '未处理', + RESOLVED: '已处理', + CLOSED: '已关闭', }; export const LINT_STATE_OPTIONS = [ @@ -467,8 +459,8 @@ export const STANDARD_TYPE = { }; export const STANDARD_TYPE_TXT = { - DEFAULT: t('默认标准'), - CUSTOM: t('自定义标准'), + DEFAULT: '默认标准', + CUSTOM: '自定义标准', }; export const STANDARD_OPTIONS = [ @@ -493,10 +485,10 @@ export const RISK_TYPE = { }; export const RISK_TYPE_TXT = { - EXHI: t('极高风险'), - HIGH: t('高风险'), - MIDD: t('中风险'), - LOW: t('低风险'), + EXHI: '极高风险', + HIGH: '高风险', + MIDD: '中风险', + LOW: '低风险', }; export const RISK_OPTIONS = [ diff --git a/web/packages/tca-analysis/src/modules/projects/index.tsx b/web/packages/tca-analysis/src/modules/projects/index.tsx index da5942ad2..a0669ccc0 100644 --- a/web/packages/tca-analysis/src/modules/projects/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/index.tsx @@ -18,14 +18,14 @@ import { getProjectRouter } from '@src/utils/getRoutePath'; import { getSchemes } from '@src/services/schemes'; import { getTmplList } from '@src/services/template'; -import { BASE_ROUTE_PREFIX, PROJECT_ROUTE_PREFIX } from '@src/common/constants'; +import { BASE_ROUTE_PREFIX, PROJECT_ROUTE_PREFIX } from '@src/constant'; import Nav from './nav'; import ProjectList from './project/project-list'; import FirstModal from './project/first-modal'; const Projects = () => { const history = useHistory(); - const { org_sid: orgSid, team_name: teamName }: any = useParams(); + const { orgSid, teamName }: any = useParams(); const { curRepo } = useStateStore(); const [schemes, setSchemes] = useState([]); const [templates, setTemplates] = useState([]); diff --git a/web/packages/tca-analysis/src/modules/projects/issues/detail-right.tsx b/web/packages/tca-analysis/src/modules/projects/issues/detail-right.tsx index 579e0b89a..8e6881b3e 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/detail-right.tsx +++ b/web/packages/tca-analysis/src/modules/projects/issues/detail-right.tsx @@ -47,7 +47,18 @@ const DetailRight = (props: DetailRightProps) => { const [visible, setVisible] = useState(false); const [ruleDetail, setRuleDetail] = useState({}); const [modalVsb, setModalVsb] = useState(false); - const { orgSid, teamName, data, repoId, projectId, schemeId, issueId, curLine, callback, scrollToLine } = props; + const { + orgSid, + teamName, + data, + repoId, + projectId, + schemeId, + issueId, + curLine, + callback, + scrollToLine, + } = props; const isHandled = data.state === 2; const members = getProjectMembers(); @@ -56,7 +67,13 @@ const DetailRight = (props: DetailRightProps) => { }, [issueId]); const getRecords = async () => { - const issueRecords = await getIssueDetailComments(orgSid, teamName, repoId, projectId, issueId); + const issueRecords = await getIssueDetailComments( + orgSid, + teamName, + repoId, + projectId, + issueId, + ); setIssueRecords(issueRecords.results || []); }; @@ -96,95 +113,124 @@ const DetailRight = (props: DetailRightProps) => { }; return ( -
-
-
-

缺陷信息

-
- 严重级别 - ({ - value: toNumber(item), - text: SEVERITY[item], - }))} - onChange={(value: any) => { - updateIssueSeverity(orgSid, teamName, repoId, projectId, issueId, toNumber(value)) - .then((res: any) => { - message.success('严重级别修改成功'); - callback(res); - }); - }} - /> -
-
- 缺陷状态 - {RESOLUTIONS[data.state] || data.state} -
-
- 责任人 - ({ - value: item.username, - text: item.nickname, - }))} - onChange={(value: any) => { - updateIssueAuthor(orgSid, teamName, repoId, projectId, issueId, value) - .then((res: any) => { - message.success('责任人修改成功'); - callback(res); - }); - }} - /> -
-
- -
-

缺陷位置

- {data.issue_details?.map((item: any) => ( - scrollToLine(item.line)} - className={cn({ [style.curLine]: curLine === item.line })} - > - 第 {item.line} 行 - - ))} -

错误原因:{data.msg}

-
- -
-
-

操作记录

- {issueRecords.map((item: any, index: number) => ( -
-
- - {find(members, { username: item.creator }) - ? find(members, { username: item.creator }).nickname - : item.creator} - - - {item.created_time - && moment(item.created_time).format('YYYY/MM/DD HH:mm:ss')} - -
-

{item.message}

-
- ))} -
- - setVisible(false)} /> - setModalVsb(false)} onOk={handleIssue} /> +
+
+
+

缺陷信息

+
+ 严重级别 + ({ + value: toNumber(item), + text: SEVERITY[item], + }))} + onChange={(value: any) => { + updateIssueSeverity( + orgSid, + teamName, + repoId, + projectId, + issueId, + toNumber(value), + ).then((res: any) => { + message.success('严重级别修改成功'); + callback(res); + }); + }} + /> +
+
+ 缺陷状态 + {RESOLUTIONS[data.state] || data.state} +
+
+ 责任人 + ({ + value: item.username, + text: item.nickname, + }))} + onChange={(value: any) => { + updateIssueAuthor( + orgSid, + teamName, + repoId, + projectId, + issueId, + value, + ).then((res: any) => { + message.success('责任人修改成功'); + callback(res); + }); + }} + /> +
+ +
+

缺陷位置

+ {data.issue_details?.map((item: any) => ( + scrollToLine(item.line)} + className={cn({ [style.curLine]: curLine === item.line })} + > + 第 {item.line} 行 + + ))} +

错误原因:{data.msg}

+
+ +
+
+

操作记录

+ {issueRecords.map((item: any, index: number) => ( +
+
+ + {find(members, { username: item.creator }) + ? find(members, { username: item.creator }).nickname + : item.creator} + + + {item.created_time + && moment(item.created_time).format('YYYY/MM/DD HH:mm:ss')} + +
+

{item.message}

+
+ ))} +
+ + setVisible(false)} + /> + setModalVsb(false)} + onOk={handleIssue} + /> +
); }; diff --git a/web/packages/tca-analysis/src/modules/projects/issues/detail.tsx b/web/packages/tca-analysis/src/modules/projects/issues/detail.tsx index 7b887cdfa..bfc49fd32 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/detail.tsx +++ b/web/packages/tca-analysis/src/modules/projects/issues/detail.tsx @@ -16,7 +16,7 @@ import SyntaxHighlighter from 'react-syntax-highlighter'; import Loading from '@src/components/loading'; import SelectBorderless from '@src/components/select-borderless'; import { getIssueDetail, getCodeFile, getProjectDetail } from '@src/services/projects'; -import themes from '@src/common/highlight-theme'; +import themes from '@src/constant/highlight-theme'; import DetailRight from './detail-right'; @@ -30,7 +30,7 @@ const Detail = () => { const [project, setProject] = useState({}) as any; const [theme, setTheme] = useState('default-style'); const [curLine, setCurLine] = useState(-1); - const { org_sid: orgSid, team_name: teamName } = params; + const { orgSid, teamName } = params; let highlightTheme = {}; try { diff --git a/web/packages/tca-analysis/src/modules/projects/issues/index.tsx b/web/packages/tca-analysis/src/modules/projects/issues/index.tsx index 7ad1c6d44..ee2e95046 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/issues/index.tsx @@ -20,7 +20,7 @@ import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { getQuery, getProjectMembers } from '@src/utils'; import Copy from '@src/components/copy'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; // import { getProjectRouter } from '@src/utils/getRoutePath'; import { getIssues, handleIssues, updateIssuesAuthor } from '@src/services/projects'; import { getLintConfig, getCheckPackages } from '@src/services/schemes'; @@ -355,10 +355,10 @@ const Issues = (props: IssuesProps) => { /> ( {name} @@ -440,12 +440,11 @@ const Issues = (props: IssuesProps) => {
{ title="批量修改责任人" onCancel={() => setUpdateAuthorVsb(false)} afterClose={() => form.resetFields()} - onOk={() => form.validateFields().then(updateAuthor)} + onOk={() => { + form.validateFields().then(updateAuthor); + }} >
void; nextIssue: () => void; onClose: () => void; @@ -44,57 +39,111 @@ interface IssueModalProps { const IssueModal = (props: IssueModalProps) => { const { - params, curSchemeId, issueId, visible, isFirstIssue, isLastIssue, - prevIssue, nextIssue, onClose, callback, + params, + issueId, + visible, + issuesData, + listLoading, + prevIssue, + nextIssue, + onClose, + callback, } = props; - const [orgSid, teamName, repoId, projectId] = params; + const [orgSid, teamName, repoId, projectId, schemeId] = params; const listRef: any = useRef({}); const rowHeights = useRef({}); - const [reloadList, setReloadList] = useState(false); // 弹框关闭后是否需要重新请求列表数据 + const [reloadList, setReloadList] = useState(false); // 弹框关闭后是否需要重新请求列表数据 const [detail, setDetail] = useState({}); const [loading, setLoading] = useState(false); const [codeFile, setCode] = useState({}); + const [isFirstIssue, setIsFirstIssue] = useState(false); + const [isLastIssue, setIsLastIssue] = useState(false); const [status, setStatus] = useState({ - severityPopVsb: false, - authorPopVsb: false, - issuePopVsb: false, - rulePopVsb: false, - issueLinePopVsb: false, + severityPopVsb: false, // 修改严重级别 popover + authorPopVsb: false, // 修改责任人 popover + issuePopVsb: false, // 处理问题 popover + issueLinePopVsb: false, // 查看问题行 popover + historyPopVsb: false, // 操作记录 popover }); - const [ruleDetail, setRuleDetail] = useState({}); - + const [expanded, setExpanded] = useState([]); // 标记问题行规则是否展开 + const [ruleDetail, setRuleDetail] = useState({}); + const { list, next, previous } = issuesData; const issueLines = detail.issue_details?.map((item: any) => item.line) ?? []; + const loadingStatus = loading || listLoading; useEffect(() => { + // 重置数据 + setExpanded([]); + setRuleDetail({}); + if (visible && issueId) { getIssueDetail(orgSid, teamName, repoId, projectId, issueId).then((res) => { const params: any = { path: res.file_path, - revision: get(res, 'issue_details[0].scan_revision'), + revision: res?.issue_details[0]?.scan_revision, }; - if (res.is_external) { // 外部代码库需要传url + if (res.is_external) { + // 外部代码库需要传url params.scm_url = res.scm_url; params.path = res.real_file_path; } setDetail(res); setLoading(true); - getCodeFile(orgSid, teamName, repoId, projectId, params).then((file) => { - setCode(file); - }) + getCodeFile(orgSid, teamName, repoId, projectId, params) + .then((response) => { + setCode(response); + }) .finally(() => { setLoading(false); - scrollToItem(res?.issue_details[0].line); + scrollToItem(res?.issue_details[0]?.line); }); + + getRuleDetailInfo(res); }); } }, [visible, issueId]); + useEffect(() => { + if (visible) { + getIssueBoundary(); + } + }, [visible, issueId, issuesData]); + + useEffect(() => { + // 重置数据, 防止在【上/下一个问题】列表需要翻页时出现脏数据展示 + if (listLoading) { + setCode({}); + setDetail({}); + } + }, [listLoading]); + + // 判断当前 Issue 是否为第一个/最后一个问题 + const getIssueBoundary = () => { + const index = findIndex(list, { id: issueId }); + // 如果路由中存在issueId,则index可能为-1,也视作第一个问题 + if (index <= 0 && !previous) { + // 第一个问题 + setIsFirstIssue(true); + } else if (isFirstIssue) { + setIsFirstIssue(false); + } + + if (index === list.length - 1 && !next) { + // 最后一个问题 + setIsLastIssue(true); + } else if (isLastIssue) { + setIsLastIssue(false); + } + }; + const scrollToItem = (line: number) => { - listRef.current?.scrollToItem(line, 'center'); + if (line && listRef.current && listRef.current.scrollToItem) { + listRef.current.scrollToItem(line, 'center'); + } }; const getRowHeight = (index: number) => { - const lineMinHeight = 30; + const lineMinHeight = 26; return rowHeights.current[index] || lineMinHeight; }; @@ -104,9 +153,11 @@ const IssueModal = (props: IssueModalProps) => { }; const rowRenderer = ({ index, style: rowStyle }: any) => { - const { lineNum: line, content = '' } = codeFile?.codeContents[index] || {}; + const { lineNum: line, content } = codeFile?.codeContents[index] ?? {}; const rowRef: any = useRef({}); - const language = detail.language ?? codeFile.suffix?.split('.')[1] ?? 'plaintext'; + const language = detail.language ?? codeFile.suffix?.split('.')[1] ?? 'plaintext'; + const issueIndex = issueLines.indexOf(line); + const fileError = line === 1 && issueLines[0] === 0; // 文件级警告 useEffect(() => { if (rowRef.current) { @@ -121,34 +172,86 @@ const IssueModal = (props: IssueModalProps) => { ref={rowRef} id={line} className={cn(style.codeContent, { - [style[`status-${detail.severity}`]]: (line === 1 && issueLines[0] === 0) || issueLines.includes(line), + [style[`status-${detail.severity}`]]: + (line === 1 && issueLines[0] === 0) || issueLines.includes(line), + [style.fileError]: line === 1 && issueLines[0] === 0, })} > - { - ( - // 本行有问题 || 问题行为0,即文件问题显示在第一行之前 - (line === 1 && issueLines[0] === 0) || issueLines.includes(line) - ) && ( -
-
-   - 【{detail.checkrule_real_name}】规则描述:{detail.checkrule_rule_title} - { - false && ( - - ) + {// 本行有问题 || 问题行为0,即文件问题显示在第一行之前 + (fileError || issueLines.includes(line)) && ( +
+
{ + if (issueIndex > -1) { + const list = cloneDeep(expanded); + list[issueIndex] = !expanded[issueIndex]; + setExpanded(list); } -
-
{detail.msg}
+ }} + > + + {expanded[issueIndex] || fileError ? ( + + ) : ( + + )} + 【{detail.checkrule_real_name}】规则描述: + {ruleDetail.rule_title} + + + {issueIndex !== 0 && !fileError && ( + document.body} + > +
- ) - } +
错误原因:{detail.msg}
+ {(expanded[issueIndex] || fileError) + && ruleDetail.checkruledesc?.desc && ( +
+

规则详细说明

+ + {ruleDetail.checkruledesc?.desc} + +
+ )} +
+ )} - {content.length > CODE_MAX_CHAR_LENGTH ? `${content.substring(0, CODE_MAX_CHAR_LENGTH)}...` : content} + {content.length > CODE_MAX_CHAR_LENGTH + ? `${content.substring(0, CODE_MAX_CHAR_LENGTH)}...` + : content} 
@@ -167,12 +270,17 @@ const IssueModal = (props: IssueModalProps) => { setStatus(obj); }; - const getRuleDetailInfo = () => { - if (isEmpty(ruleDetail)) { - getRuleDetail(orgSid, teamName, repoId, curSchemeId, detail.checkrule_gid).then((res: any) => { - setRuleDetail(res); - }); - } + const getRuleDetailInfo = (issueDetail: any) => { + getRuleDetailByName( + orgSid, + teamName, + repoId, + schemeId, + issueDetail.checktool_name, + issueDetail.checkrule_real_name, + ).then((res: any) => { + setRuleDetail(res); + }); }; // 关闭弹框之后重置状态 @@ -193,10 +301,17 @@ const IssueModal = (props: IssueModalProps) => { centered title={
-

{detail.file_path?.split('/').pop()}

- - - +

+ {detail.file_path?.split('/').pop()} + + 文件路径:{detail.file_path} + + +

+ {/* todo: 全屏查看issue */} + {/* + + */}
} width={1000} @@ -208,8 +323,6 @@ const IssueModal = (props: IssueModalProps) => { >
@@ -230,9 +343,8 @@ const IssueModal = (props: IssueModalProps) => { }} />
- {loading ? ( - - ) : ( + {loadingStatus && } + {!loadingStatus && codeFile.codeContents && ( {({ height, width }: any) => ( { )} )} + {!loadingStatus && codeFile.code === -1 && codeFile.cd_error && ( +
+

问题所在行

+ {issueLines?.map((line: number) => ( + + 第 {line} 行 + + ))} + +

错误原因

+

{detail.msg}

+ +

+ 代码拉取失败, + {codeFile.cd_error} +

+

处理建议

+

1. 代码库帐号密码问题。

+

2. 文件格式无法展示 —— 不支持展示.jar等二进制文件。

+

+ 3. 代码文件不存在 —— + 可能为本地分析中间代码,请在本地环境下查看代码或者联系管理员定位问题。{' '} +

+
+ )}
- - + +
); }; export default IssueModal; - diff --git a/web/packages/tca-analysis/src/modules/projects/issues/rule-detail.tsx b/web/packages/tca-analysis/src/modules/projects/issues/rule-detail.tsx index 719bc038e..9715be659 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/rule-detail.tsx +++ b/web/packages/tca-analysis/src/modules/projects/issues/rule-detail.tsx @@ -9,10 +9,12 @@ */ import React from 'react'; import cn from 'classnames'; +import { Link, useParams } from 'react-router-dom'; import ReactMarkdown from 'react-markdown'; import { get } from 'lodash'; import { Drawer } from 'coding-oa-uikit'; +import { getToolsRouter } from '@src/utils/getRoutePath'; import style from './style.scss'; @@ -24,58 +26,69 @@ interface RuleDetailProps { const RuleDetail = (props: RuleDetailProps) => { const { data, visible, onClose } = props; + const { orgSid } = useParams(); + console.log(data); return ( - -
- 展示名称 - {data.display_name || '--'} -
- {/*
- 实际名称 - {data.real_name || '--'} -
*/} + +
+ 规则名称 + {data.real_name || '--'} +
-
- 规则概述 - {data.rule_title || '--'} -
-
- 责任人 - {data.creator || '--'} -
-
- 规则状态 - {data.disable ? '禁用' : '活跃'} -
-
- 适用语言 - {(data.languages?.join(' | ')) || '--'} -
-
- 分类 - {data.category_name || '--'} -
-
- 严重级别 - {data.severity_name || '--'} -
-
- 详细描述 -
- {get(data, 'checkruledesc.desc') && ( -
- {/* eslint-disable-next-line */} - -
- )} -
+
+ 规则概述 + {data.rule_title || '--'} +
+
+ 所属工具 + {data?.checktool?.display_name ? ( + + {data?.checktool?.display_name} + + ) : ( + -- + )} +
+
+ 责任人 + {data.creator || '--'} +
+
+ 规则状态 + {data.disable ? '禁用' : '活跃'} +
+
+ 适用语言 + {data.languages?.join(' | ') || '--'} +
+
+ 分类 + {data.category_name || '--'} +
+
+ 严重级别 + {data.severity_name || '--'} +
+
+ 详细描述 +
+ {get(data, 'checkruledesc.desc') && ( +
+ {/* eslint-disable-next-line */} + +
+ )} +
); }; diff --git a/web/packages/tca-analysis/src/modules/projects/issues/search.tsx b/web/packages/tca-analysis/src/modules/projects/issues/search.tsx index 12179d4d2..323e9b548 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/search.tsx +++ b/web/packages/tca-analysis/src/modules/projects/issues/search.tsx @@ -156,12 +156,12 @@ const Search = (props: SearchProps) => { onChange={(value: any) => value && onChange('checkpackage', value)} /> - + onChange('checkrule_display_name', value)} + onSearch={(value: string) => onChange('checkrule_real_name', value)} /> diff --git a/web/packages/tca-analysis/src/modules/projects/issues/style.scss b/web/packages/tca-analysis/src/modules/projects/issues/style.scss index f165bfa99..8fddf3cf5 100644 --- a/web/packages/tca-analysis/src/modules/projects/issues/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/issues/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .operation { position: absolute; @@ -246,6 +246,27 @@ vertical-align: inherit !important; } } + + .modal-desc{ + margin-left: 8px; + } + + .modal-desc, .copy-icon{ + font-size: 12px; + color: #606c80; + } + } + + .code-error { + margin-top: 30px; + + p { + margin-bottom: 16px; + } + + .error-desc { + color: #eb333f; + } } .wrapper { @@ -285,6 +306,7 @@ .code-wrapper { height: 800px; + height: calc(100vh - 340px); padding-left: 20px; .row { @@ -301,19 +323,51 @@ .code-content { flex: 1; - padding-left: 10px; + // padding-left: 10px; + + pre { + padding-left: 10px; + } .rule-wrapper { padding-top: 6px; + padding-right: 10px; + padding-left: 10px; + + .rule { + display: flex; + justify-content: space-between; + cursor: pointer; + + button { + height: 26px; + } + + .rule-content { + color: #202d40; + } + } .rule-desc { + color: #606c80; + font-size: 13px; padding-left: 17px; margin-top: 2px; + line-height: 2; + max-height: 300px; + overflow: auto; + + h4 { + color: #606c80; + margin-top: 16px; + font-size: 14px; + } } - .rule-detail { - padding-left: 6px; - font-size: 13px; + .issue-msg { + padding-left: 20px; + margin: 6px 0; + // font-size: 13px; } } @@ -321,21 +375,37 @@ &-1 { background-color: $fatal-bg; color: $fatal-color; + + pre { + background-color: $fatal-bg; + } } &-2 { background-color: $error-bg; color: $error-color; + + pre { + background-color: $error-bg; + } } &-3 { background-color: $warging-bg; color: $warging-color; + + pre { + background-color: $warging-bg; + } } &-4 { background-color: $tip-bg; color: $tip-color; + + pre { + background-color: $tip-bg; + } } } } diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/detail.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/detail.tsx index e5f8ed3db..46887eb12 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/detail.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/detail.tsx @@ -27,7 +27,7 @@ const Detail = () => { const listRef: any = useRef({}); const rowHeights = useRef({}); // const rowRef: any = useRef({}); - const { org_sid: orgSid, team_name: teamName, repoId, projectId, fileId } = useParams() as any; + const { orgSid, teamName, repoId, projectId, fileId } = useParams() as any; const [codeFile, setCodeFile] = useState({}) as any; const [fileInfo, setFileInfo] = useState({}) as any; const [issues, setIssues] = useState({ diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/index.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/index.tsx index 13d8f7d43..a58d44a80 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/index.tsx @@ -17,7 +17,7 @@ import { Table, Avatar } from 'coding-oa-uikit'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { getQuery } from '@src/utils'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getProjectRouter } from '@src/utils/getRoutePath'; import { getCCFilesIssues } from '@src/services/projects'; import { CC_CHANGE_TYPE_CHOICES } from '../../constants'; diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/style.scss index 3e3b4136d..074beb68a 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccfiles/style.scss @@ -1,9 +1,9 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; @import '../common/common.scss'; .file-detail { - height: calc(100% - 87px); + height: calc(100vh - 48px); .header { display: flex; diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/detail.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/detail.tsx index 2e6a3d183..568caa79f 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/detail.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/detail.tsx @@ -49,7 +49,7 @@ const CcIssueDetail = () => { const offsetLine = 10; const params: any = useParams(); - const { org_sid: orgSid, team_name: teamName } = params; + const { orgSid, teamName } = params; const repoId = toNumber(params.repoId); const projectId = toNumber(params.projectId); diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/index.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/index.tsx index 6788bca68..fe5c2900c 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/index.tsx @@ -16,7 +16,7 @@ import { Table, Avatar } from 'coding-oa-uikit'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { getQuery } from '@src/utils'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getProjectRouter } from '@src/utils/getRoutePath'; import { getCCFunIssues } from '@src/services/projects'; import { CC_CHANGE_TYPE_CHOICES } from '../../constants'; diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx index f58574d67..bfa34e162 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx @@ -156,7 +156,7 @@ const IssueModal = (props: IssueModalProps) => { -

圈复杂度说明

+

圈复杂度说明

定义:数量上表现为独立执行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。

关键:圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。

修复建议:建议通过重构方法、简化条件表达式等手段来降低方法的圈复杂度。

diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss index 5607b7f16..8ba122233 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; // @import '../common/common.scss'; .ccissues { diff --git a/web/packages/tca-analysis/src/modules/projects/metric/clocs/index.tsx b/web/packages/tca-analysis/src/modules/projects/metric/clocs/index.tsx index 85682d3c7..c3f2daeab 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/clocs/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/clocs/index.tsx @@ -9,12 +9,12 @@ */ import React, { useEffect, useState } from 'react'; import { Tree, Row, Col, Descriptions, Tooltip, Tag, Button } from 'coding-oa-uikit'; +import { useTranslation } from 'react-i18next'; import QuestionCircleIcon from 'coding-oa-uikit/lib/icon/QuestionCircle'; import ArrowLeftIcon from 'coding-oa-uikit/lib/icon/ArrowLeft'; import { forEach, get } from 'lodash'; // 项目内 -import { t } from '@src/i18n/i18next'; import NoDataSVG from '@src/images/no-data.svg'; import { getClocFiles } from '@src/services/projects'; import s from '../style.scss'; @@ -34,75 +34,6 @@ interface DataNode { children?: DataNode[]; } -/** - * 将请求数据格式化为tree所需数据 - * @param data getClocFiles返回数据 - */ -const formatData = (data: any) => { - const nodes: Array = []; - forEach(data, (value, key) => { - switch (key) { - case 'dirs': - forEach(value.results, (info) => { - const dict: any = { - info, - }; - if (info.dir_path) { - if (info.parent_path) { - // 父目录不为根目录 - // eslint-disable-next-line - dict.title = info.dir_path.split(`${info.parent_path}/`)[1]; - } else { - // 父目录为根目录 - dict.title = info.dir_path; - } - dict.key = info.dir_path; - nodes.push(dict); - } - }); - break; - case 'files': - forEach(value.results, (info) => { - let title = info.file_name; - switch (info.change_type) { - case CHANGE_TYPE.ADD: - title = ( - <> - {t('新增')} {title} - - ); - break; - case CHANGE_TYPE.MOD: - title = ( - <> - {t('修改')} {title} - - ); - break; - case CHANGE_TYPE.DEL: - title = ( - <> - {t('修改')} {title} - - ); - break; - default: - break; - } - nodes.push({ - info, - title, - isLeaf: true, - key: info.dir_path ? `${info.dir_path}/${info.file_name}` : info.file_name, - }); - }); - break; - default: - break; - } - }); - return nodes; -}; interface IProps { orgSid: string; @@ -115,6 +46,7 @@ const Clocs = ({ orgSid, teamName, repoId, projectId }: IProps) => { const [treeData, setTreeData] = useState>([]); const [rootNodeInfo, setRootNodeInfo] = useState({}); const [selectNodeInfo, setSelectNodeInfo] = useState({}); + const { t } = useTranslation(); useEffect(() => { // 初始化获取根节点数据 @@ -131,6 +63,76 @@ const Clocs = ({ orgSid, teamName, repoId, projectId }: IProps) => { }); }, [projectId]); + /** + * 将请求数据格式化为tree所需数据 + * @param data getClocFiles返回数据 + */ + const formatData = (data: any) => { + const nodes: Array = []; + forEach(data, (value, key) => { + switch (key) { + case 'dirs': + forEach(value.results, (info) => { + const dict: any = { + info, + }; + if (info.dir_path) { + if (info.parent_path) { + // 父目录不为根目录 + // eslint-disable-next-line + dict.title = info.dir_path.split(`${info.parent_path}/`)[1]; + } else { + // 父目录为根目录 + dict.title = info.dir_path; + } + dict.key = info.dir_path; + nodes.push(dict); + } + }); + break; + case 'files': + forEach(value.results, (info) => { + let title = info.file_name; + switch (info.change_type) { + case CHANGE_TYPE.ADD: + title = ( + <> + {t('新增')} {title} + + ); + break; + case CHANGE_TYPE.MOD: + title = ( + <> + {t('修改')} {title} + + ); + break; + case CHANGE_TYPE.DEL: + title = ( + <> + {t('修改')} {title} + + ); + break; + default: + break; + } + nodes.push({ + info, + title, + isLeaf: true, + key: info.dir_path ? `${info.dir_path}/${info.file_name}` : info.file_name, + }); + }); + break; + default: + break; + } + }); + return nodes; + }; + /** * 切换时,选中节点信息 * @param keys diff --git a/web/packages/tca-analysis/src/modules/projects/metric/common/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/common/style.scss index 52718b195..383e7c391 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/common/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/metric/common/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .file-path { text-overflow: ellipsis; diff --git a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/detail.tsx b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/detail.tsx index f0769a8af..f3af4e02d 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/detail.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/detail.tsx @@ -8,7 +8,17 @@ import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { get, isEmpty, toNumber } from 'lodash'; -import { Row, Col, Button, Dropdown, Menu, Select, message, Input, Popover } from 'coding-oa-uikit'; +import { + Row, + Col, + Button, + Dropdown, + Menu, + Select, + message, + Input, + Popover, +} from 'coding-oa-uikit'; import AngleDown from 'coding-oa-uikit/lib/icon/AngleDown'; import AngleUp from 'coding-oa-uikit/lib/icon/AngleUp'; import DotCircle from 'coding-oa-uikit/lib/icon/DotCircle'; @@ -59,14 +69,20 @@ const DupDetail = () => { const { curRepo } = useStateStore(); const params: any = useParams(); - const { org_sid: orgSid, team_name: teamName } = params; + const { orgSid, teamName } = params; const repoId = toNumber(params.repoId); const projectId = toNumber(params.projectId); const issueId = toNumber(params.issueId); // 获取重复代码issue信息 const getIssueDetail = async () => { - const detail = await getDupIssuesDetail(orgSid, teamName, repoId, projectId, issueId); + const detail = await getDupIssuesDetail( + orgSid, + teamName, + repoId, + projectId, + issueId, + ); setDupFileIssueDetail(detail); return detail; }; @@ -92,9 +108,16 @@ const DupDetail = () => { // 获取当前issue文件的重复块 const getIssueCodeBlocks = async (blockNum: number) => { - const res = await getDupFileBlocks(orgSid, teamName, repoId, projectId, issueId, { - limit: blockNum, - }); + const res = await getDupFileBlocks( + orgSid, + teamName, + repoId, + projectId, + issueId, + { + limit: blockNum, + }, + ); const blocks = res.results; setLeftFileBlocks(blocks); return blocks; @@ -193,13 +216,11 @@ const DupDetail = () => { default: break; } - if (request) { - request.then(() => { - message.success('修改成功'); - setAuthorPopVsb(false); - getIssueDetail(); - }); - } + request?.then(() => { + message.success('修改成功'); + setAuthorPopVsb(false); + getIssueDetail(); + }); }; const handleSelectBlockClick = (e: any) => { @@ -212,8 +233,10 @@ const DupDetail = () => { if ( !( relatedBlock - && relatedBlock.duplicate_file.file_path === block.duplicate_file.file_path - && relatedBlock.duplicate_file.scm_revision === block.duplicate_file.scm_revision + && relatedBlock.duplicate_file.file_path + === block.duplicate_file.file_path + && relatedBlock.duplicate_file.scm_revision + === block.duplicate_file.scm_revision ) ) { getCodeFile( @@ -230,7 +253,12 @@ const DupDetail = () => { selectRelateBlockClick(block); }; - const selectPreOrNextClick = (index: number, blocks: Array, block: any, type: string) => { + const selectPreOrNextClick = ( + index: number, + blocks: Array, + block: any, + type: string, + ) => { const findex = blocks.findIndex(item => item.id === block.id); const newBlock = blocks[findex + index]; if (newBlock) { @@ -306,46 +334,58 @@ const DupDetail = () => {
{blockNum} 块重复
{' '}
- 责任人{issue.owner} - { - issue.state === DUP_FILE_STATE_ENUM.ACTIVE && ( - - setAuthor(e.target.value)} - /> -
- - + -
+ }} + > + 取消 +
- - } - > - { + + } + > + { setAuthorPopVsb(!authorPopVsb); - }} /> - } - title='修改责任人' - /> - - ) - } + }} + /> + } + title="修改责任人" + /> + + )}
状态 @@ -364,8 +404,8 @@ const DupDetail = () => { {blockDetail && ( - 当前查看的{blockDetail.start_line_num} - {blockDetail.end_line_num}{' '} - 行代码被 {lastModifier}最近修改过 + 当前查看的{blockDetail.start_line_num} -{' '} + {blockDetail.end_line_num} 行代码被 {lastModifier}最近修改过 )} @@ -399,8 +439,7 @@ const DupDetail = () => {

{item.duplicate_file.file_name}

- 对比行:{item.start_line_num} -{' '} - {item.end_line_num} + 对比行:{item.start_line_num} - {item.end_line_num}
文件路径:{item.duplicate_file.dir_path}
@@ -415,8 +454,8 @@ const DupDetail = () => {
- 代码块:{relatedBlock.start_line_num} - {relatedBlock.end_line_num}{' '} - 行 + 代码块:{relatedBlock.start_line_num} -{' '} + {relatedBlock.end_line_num} 行
{' '}
{relatedBlock.last_modifier} 最近修改过 @@ -431,7 +470,11 @@ const DupDetail = () => { ); // 渲染代码块 - const renderCodeContainer = (codefile: any, block: any, resetScrollToLine = false) => ( + const renderCodeContainer = ( + codefile: any, + block: any, + resetScrollToLine = false, + ) => (
{codefile ? ( {
diff --git a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx index ad3d20000..e9be2de55 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx @@ -16,7 +16,7 @@ import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { getQuery } from '@src/utils'; import { getDupIssues } from '@src/services/projects'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getProjectRouter } from '@src/utils/getRoutePath'; import { DUP_FILE_STATE_OPTIONS } from '../../constants'; diff --git a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/style.scss index 4c6a9499e..49a0d0bbd 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .table-search-top { height: 30px; @@ -247,7 +247,7 @@ hr { .dup-file-container { min-width: 1220px; - height: 100%; + height: calc(100vh - 48px); .left-container, .right-container { diff --git a/web/packages/tca-analysis/src/modules/projects/metric/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/style.scss index 5651d2cde..0b67168a4 100644 --- a/web/packages/tca-analysis/src/modules/projects/metric/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/metric/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .cc-search-header { margin-bottom: 12px; diff --git a/web/packages/tca-analysis/src/modules/projects/nav.tsx b/web/packages/tca-analysis/src/modules/projects/nav.tsx index ed722a0d6..012e72568 100644 --- a/web/packages/tca-analysis/src/modules/projects/nav.tsx +++ b/web/packages/tca-analysis/src/modules/projects/nav.tsx @@ -17,8 +17,12 @@ import LinkIcon from 'coding-oa-uikit/lib/icon/Link'; import SelectDropdown from '@src/components/select-dropdown'; import { useStateStore } from '@src/context/store'; import { getProjectRouter, getSchemeRouter } from '@src/utils/getRoutePath'; -import { PROJECT_ROUTE_PREFIX } from '@src/common/constants'; -import { getProjectDetail, getBranchs, getSchemesByBranch } from '@src/services/projects'; +import { PROJECT_ROUTE_PREFIX } from '@src/constant'; +import { + getProjectDetail, + getBranchs, + getSchemesByBranch, +} from '@src/services/projects'; import ScanModal from './project/scan-modal'; import NewProjectModal from './project/new-project-modal'; @@ -49,7 +53,7 @@ const Nav = ({ allSchemes, templates }: NavProps) => { const repoId = toNumber(params.repoId); const projectId = toNumber(params.projectId); - const { org_sid: orgSid, team_name: teamName } = params; + const { orgSid, teamName } = params; let curTab = params.tabs; if (curTab === 'metric') { @@ -65,7 +69,12 @@ const Nav = ({ allSchemes, templates }: NavProps) => { const getData = async () => { const project = await getProjectDetail(orgSid, teamName, repoId, projectId); const branch = await getBranchs(orgSid, teamName, repoId); - const scheme = await getSchemesByBranch(orgSid, teamName, repoId, project.branch); + const scheme = await getSchemesByBranch( + orgSid, + teamName, + repoId, + project.branch, + ); setCurProject(project); setBranchs(branch.results || []); @@ -80,7 +89,8 @@ const Nav = ({ allSchemes, templates }: NavProps) => { }; const getSchemes = (branch: string) => { - branch && (async () => setSchemes(await getSchemesByBranch(orgSid, teamName, curRepo.id, branch)))(); + branch + && (async () => setSchemes(await getSchemesByBranch(orgSid, teamName, curRepo.id, branch)))(); }; const onChangeBranch = async (branch: any) => { @@ -97,20 +107,28 @@ const Nav = ({ allSchemes, templates }: NavProps) => {
({ value: item.branch, text: item.branch }))} - onSelect={(item: any) => onChangeBranch(item.key)} + data={branchs.map((item: any) => ({ + value: item.branch, + text: item.branch, + }))} + onSelect={(item: any) => { + onChangeBranch(item.key); + }} /> ({ value: item.scan_scheme__name, text: item.scan_scheme__name }))} + data={schemes.map((item: any) => ({ + value: item.scan_scheme__name, + text: item.scan_scheme__name, + }))} onSelect={(item: any) => { const id = find(schemes, { scan_scheme__name: item.key })?.id; history.push(`${getProjectRouter(orgSid, teamName, repoId, id)}/overview`); @@ -130,7 +148,10 @@ const Nav = ({ allSchemes, templates }: NavProps) => {
- , scan === 'client' && , @@ -128,7 +136,7 @@ const ScanModal = (props: ScanModalProps) => { form={form} initialValues={{ scan: 'web', - total_scan: false + total_scan: false, }} > { const intervalRef = useRef(); const history = useHistory(); - const { org_sid: orgSid, team_name: teamName, repoId, projectId, jobId, scanTab } = useParams() as any; + const { orgSid, teamName, repoId, projectId, jobId, scanTab } = useParams() as any; const [data, setData] = useState({}); const [curTask, setCurTask] = useState({}); const taskRef = useRef() as any; // 存储当前任务的id,解决定时器中的闭包问题 - 获取不到最新的 curTask 值 @@ -105,9 +105,9 @@ const ScanDetail = () => { const a = document.createElement('a'); a.href = decodeURIComponent(url) || ''; // 替换为前端域名地址 - let pathname = a.pathname + let { pathname } = a; if (!pathname.startsWith('/server')) { - pathname = `/server${pathname}` + pathname = `/server${pathname}`; } url = `${window.location.origin}${pathname}`; const filename = url.substr(url.lastIndexOf('/') + 1); @@ -266,7 +266,7 @@ const ScanDetail = () => {

任务执行情况 - Job ID: {jobId} + Job ID: {jobId} Scan ID: {data?.scan_id} { orgSid, teamName, repoId, - data?.project?.scan_scheme + data?.project?.scan_scheme, )}/basic`} rel="noreferrer" >查看分析方案

@@ -287,13 +287,12 @@ const ScanDetail = () => {
- history.push(`${getProjectRouter( - orgSid, - teamName, - repoId, - projectId - )}/scan-history/${jobId}/${tab}`) + onChange={(tab: string) => history.push(`${getProjectRouter( + orgSid, + teamName, + repoId, + projectId, + )}/scan-history/${jobId}/${tab}`) } > @@ -418,7 +417,7 @@ const ScanDetail = () => { ))}
- )} + )} {item.node?.name && (

执行机器: {item.node.name}

)} diff --git a/web/packages/tca-analysis/src/modules/projects/scan-history/index.tsx b/web/packages/tca-analysis/src/modules/projects/scan-history/index.tsx index f69e48f74..0db34b790 100644 --- a/web/packages/tca-analysis/src/modules/projects/scan-history/index.tsx +++ b/web/packages/tca-analysis/src/modules/projects/scan-history/index.tsx @@ -19,7 +19,7 @@ import RunningIcon from '@src/components/running-icon'; import Tips from '@src/components/tips'; import { getScans, cancelScan } from '@src/services/projects'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { formatDate, secondToDate, getQuery } from '@src/utils'; import { getProjectRouter } from '@src/utils/getRoutePath'; @@ -45,7 +45,7 @@ const ScanHistory = (props: ScanHistoryProps) => { const query = getQuery(); const history = useHistory(); const timer = useRef(); - const isUnmounted = useRef(false) + const isUnmounted = useRef(false); const [count, setCount] = useState(DEFAULT_PAGER.count); const [list, setList] = useState([]); @@ -65,8 +65,8 @@ const ScanHistory = (props: ScanHistoryProps) => { useEffect(() => { getListData(); return () => { - isUnmounted.current = true - } + isUnmounted.current = true; + }; }, [projectId]); useEffect(() => { @@ -78,7 +78,7 @@ const ScanHistory = (props: ScanHistoryProps) => { limit, offset, }; - isUnmounted.current = false + isUnmounted.current = false; getScans(orgSid, teamName, repoId, projectId, params).then((response) => { if (!isUnmounted.current) { const results = response.results || []; @@ -155,44 +155,52 @@ const ScanHistory = (props: ScanHistoryProps) => { title="分析版本" dataIndex="current_revision" render={(version: string) => version && ( - - {version.substring(0, 8)} - - message.success('复制成功')} - > - - - - + + {version.substring(0, 8)} + + { + message.success('复制成功'); + }} + > + + + + ) } /> -

等待耗时:{secondToDate(toNumber(data.waiting_time))}

-

执行耗时:{secondToDate(toNumber(data.execute_time))}

- }> - {time ? secondToDate(toNumber(time)) : '--'} -
} + render={(time: string, data: any) => ( + +

等待耗时:{secondToDate(toNumber(data.waiting_time))}

+

执行耗时:{secondToDate(toNumber(data.execute_time))}

+ + } + > + {time ? secondToDate(toNumber(time)) : '--'} +
+ )} /> (status === null ? ( - <> - - 执行中 - + <> + + 执行中 + ) : ( -
- - {data.result_code_msg} - {data.result_msg && } -
+
+ + {data.result_code_msg} + {data.result_msg && } +
)) } /> @@ -209,17 +217,33 @@ const ScanHistory = (props: ScanHistoryProps) => { <> 详情 + to={`${getProjectRouter( + orgSid, + teamName, + repoId, + projectId, + )}/scan-history/${data.job_gid}`} + > + 详情 + 结果 + to={`${getProjectRouter( + orgSid, + teamName, + repoId, + projectId, + )}/scan-history/${data.job_gid}/result`} + > + 结果 + {data.result_code === null && ( diff --git a/web/packages/tca-analysis/src/modules/projects/scan-history/result.tsx b/web/packages/tca-analysis/src/modules/projects/scan-history/result.tsx index 992a6e2ea..96a1d8787 100644 --- a/web/packages/tca-analysis/src/modules/projects/scan-history/result.tsx +++ b/web/packages/tca-analysis/src/modules/projects/scan-history/result.tsx @@ -18,32 +18,33 @@ import { getProjectRouter } from '@src/utils/getRoutePath'; import style from './style.scss'; interface ResultProps { - scanId: number; + scanId: number; } const Result = (props: ResultProps) => { - const { org_sid: orgSid, team_name: teamName, repoId, projectId } = useParams() as any; - const { scanId } = props; - const [data, setData] = useState({}); - const [loading, setLoading] = useState(true); - const { lintscan, cyclomaticcomplexityscan, duplicatescan, clocscan } = data; + const { orgSid, teamName, repoId, projectId } = useParams() as any; + const { scanId } = props; + const [data, setData] = useState({}); + const [loading, setLoading] = useState(true); + const { lintscan, cyclomaticcomplexityscan, duplicatescan, clocscan } = data; - useEffect(() => { - if (scanId) { - setLoading(true); - getScansResult(orgSid, teamName, repoId, projectId, scanId).then((response) => { - setData(response) - }).finally(() => { - setLoading(false); - }) - } - }, [scanId]); + useEffect(() => { + if (scanId) { + setLoading(true); + getScansResult(orgSid, teamName, repoId, projectId, scanId).then((response) => { + setData(response); + }) + .finally(() => { + setLoading(false); + }); + } + }, [scanId]); - if (loading) { - return ; - } + if (loading) { + return ; + } - return ( + return (

代码检查

@@ -52,10 +53,10 @@ const Result = (props: ResultProps) => { 新增问题 {lintscan.issue_open_num} 个(已聚合数据) @@ -64,10 +65,10 @@ const Result = (props: ResultProps) => { 关闭问题 {lintscan.issue_fix_num} 个{' '} @@ -77,7 +78,7 @@ const Result = (props: ResultProps) => { ) : (

暂无数据

- )} + )}

圈复杂度

@@ -89,10 +90,10 @@ const Result = (props: ResultProps) => { 新增/变化 {cyclomaticcomplexityscan.diff_cc_num} 个高复杂度方法{' '} @@ -104,7 +105,7 @@ const Result = (props: ResultProps) => { ) : (

暂无数据

- )} + )}

重复代码

@@ -125,7 +126,7 @@ const Result = (props: ResultProps) => { ) : (

暂无数据

- )} + )}

代码统计

@@ -166,10 +167,10 @@ const Result = (props: ResultProps) => { ) : (

暂无数据

- )} + )}
- ); + ); }; export default Result; diff --git a/web/packages/tca-analysis/src/modules/projects/scan-history/style.scss b/web/packages/tca-analysis/src/modules/projects/scan-history/style.scss index 9047608cc..b418a2580 100644 --- a/web/packages/tca-analysis/src/modules/projects/scan-history/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/scan-history/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .scans { :global(.ant-table-thead > tr:first-child > th) { diff --git a/web/packages/tca-analysis/src/modules/projects/style.scss b/web/packages/tca-analysis/src/modules/projects/style.scss index 08e53ade3..7d867e1e9 100644 --- a/web/packages/tca-analysis/src/modules/projects/style.scss +++ b/web/packages/tca-analysis/src/modules/projects/style.scss @@ -1,119 +1,107 @@ -@import '@src/common/style/color.scss'; +@import "@tencent/micro-frontend-shared/style/color.scss"; .project-list { - padding: 0 30px; - - :global(.ant-table) { - font-size: 13px; - } - - :global(.ant-table-tbody) { - &>tr { - td>.link-name { - color: $grey-8; - } - - &:hover { - td>.link-name { - color: $blue-5 !important; - } - } + :global(.ant-table-thead > tr > th) { + border-top: none; + } + + :global(.ant-table-tbody) { + & > tr { + td > .link-name { + color: $grey-8; + } + + &:hover { + td > .link-name { + color: $blue-5 !important; } + } } + } - :global(.ant-pagination) { - width: 100%; - } - - + .link { + color: $blue-5; + } - .link { - color: $blue-5; + .project-search { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 30px; + min-height: 48px; + border-bottom: 1px solid #dadfe6; + background-color: #fcfcfa; + + .title { + display: inline-block; + font-size: 14px; + color: $grey-8; + margin-right: 16px; + margin-bottom: 0; + padding-right: 16px; + border-right: 1px solid #f0f0f0; } - .project-search { - margin: 20px 0; - - .title { - display: inline-block; - font-size: 18px; - color: $grey-8; - - margin-right: 20px; - margin-bottom: 0; - padding-right: 20px; - border-right: 1px solid #f0f0f0; - - .icon { - color: $grey-6; - margin-left: 4px; - margin-bottom: 3px; - - &:hover { - color: $grey-8; - } - - cursor: pointer; - } - } - - .search-item { - margin-right: 15px; - } + .search-item { + margin-right: 16px; } + } } +.project-content { + padding: 0 30px; +} .nav { - .search-bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 30px; - height: 48px; - background-color: rgba($color: #fcfcfc, $alpha: 0.98); - box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1), - 0px 0.5px 0px 0px rgba(0, 0, 0, 0.08); - } + .search-bar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 30px; + height: 48px; + background-color: rgba($color: #fcfcfc, $alpha: 0.98); + box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1), + 0px 0.5px 0px 0px rgba(0, 0, 0, 0.08); + } - .dropdown { - margin-right: 16px; - } + .dropdown { + margin-right: 16px; + } - .tabs { - padding: 0 30px; + .tabs { + padding: 0 30px; - :global(.ant-tabs-tab) { - font-size: 16px; - padding: 12px 10px; - } + :global(.ant-tabs-tab) { + font-size: 16px; + padding: 12px 10px; + } - :global(.ant-tabs-nav) { - margin: 0; - } + :global(.ant-tabs-nav) { + margin: 0; + } - :global(.ant-tabs-tabpane) { - position: relative; - min-height: 500px; - } + :global(.ant-tabs-tabpane) { + position: relative; + min-height: 500px; } + } } .new-project-modal { - .tmpl { - display: flex; - justify-content: space-between; - - .tmpl-tag { - color: $cyan-6; - border-color: $cyan-6; - background-color: #fff; - border-radius: 2px; - - &.sys { - color: $grey-7; - border: 1px solid $grey-7; - } - } + .tmpl { + display: flex; + justify-content: space-between; + + .tmpl-tag { + color: $cyan-6; + border-color: $cyan-6; + background-color: #fff; + border-radius: 2px; + + &.sys { + color: $grey-7; + border: 1px solid $grey-7; + } } -} \ No newline at end of file + } +} diff --git a/web/packages/tca-analysis/src/modules/repos/constants.ts b/web/packages/tca-analysis/src/modules/repos/constants.ts index f2f25b24f..0a0c6254b 100644 --- a/web/packages/tca-analysis/src/modules/repos/constants.ts +++ b/web/packages/tca-analysis/src/modules/repos/constants.ts @@ -4,7 +4,6 @@ // See LICENSE for details // ============================================================================== -import { t } from '@src/i18n/i18next'; /** * 代码库页面的tab 切换 @@ -16,9 +15,9 @@ export const REPO_TAB_TYPE = { }; export const REPO_TAB_TYPE_TXT = { - MEMBER: t('成员权限'), - AUTH: t('认证方式'), - OVERVIEW: t('仓库信息'), + MEMBER: '成员权限', + AUTH: '认证方式', + OVERVIEW: '仓库信息', }; export const REPO_TAB_OPTIONS = [ @@ -46,9 +45,9 @@ export const AUTH_TYPE = { }; export const AUTH_TYPE_TXT = { - HTTP: t('用户名 + 密码'), - SSH: t('ssh'), - OAUTH: t('OAuth'), + HTTP: '用户名 + 密码', + SSH: 'ssh', + OAUTH: 'OAuth', }; export const AUTH_TYPE_OPTIONS = [ @@ -96,10 +95,10 @@ export const DEFAULT_SCM_PLATFORM = [ ]; export const SCM_PLATFORM = { - 1: t('其他'), - 2: t('腾讯工蜂'), - 3: t('CODING'), - 4: t('GitHub'), - 5: t('Gitee'), - 6: t('GitLab'), -}; \ No newline at end of file + 1: '其他', + 2: '腾讯工蜂', + 3: 'CODING', + 4: 'GitHub', + 5: 'Gitee', + 6: 'GitLab', +}; diff --git a/web/packages/tca-analysis/src/modules/repos/create.tsx b/web/packages/tca-analysis/src/modules/repos/create.tsx index 7cacf7369..7d7753ba9 100644 --- a/web/packages/tca-analysis/src/modules/repos/create.tsx +++ b/web/packages/tca-analysis/src/modules/repos/create.tsx @@ -6,6 +6,7 @@ import React, { useEffect, useState } from 'react'; import { useHistory, useParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import { Form, Select, Input, Button, message } from 'coding-oa-uikit'; // Radio import { get, isEmpty, filter } from 'lodash'; @@ -14,12 +15,10 @@ import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh'; // 项目内 import { useStateStore, useDispatchStore } from '@src/context/store'; -import { SCM_PLATFORM } from '@src/common/constants'; import { SET_CUR_REPO, SET_REPOS } from '@src/context/constant'; import { getScmAccounts, postRepo, getSSHInfo, getOAuthInfo, getPlatformStatus } from '@src/services/repos'; -import { t } from '@src/i18n/i18next'; import { getPCAuthRouter, getRepoRouter } from '@src/modules/repos/routes'; -import { AUTH_TYPE, AUTH_TYPE_TXT, REPO_TYPE, REPO_TYPE_OPTIONS } from './constants'; +import { AUTH_TYPE, AUTH_TYPE_TXT, REPO_TYPE, REPO_TYPE_OPTIONS, SCM_PLATFORM } from './constants'; import s from './style.scss'; const { Option, OptGroup } = Select; @@ -50,8 +49,9 @@ const Create = () => { const history = useHistory(); const { repos } = useStateStore(); const dispatch = useDispatchStore(); + const { t } = useTranslation(); - const { org_sid: orgSid, team_name: teamName }: any = useParams(); + const { orgSid, teamName }: any = useParams(); // const [allAuthList, setAllAuthList] = useState>([]); const [sshAuthList, setSshAuthList] = useState([]); const [httpAuthList, setHttpAuthList] = useState([]); @@ -74,11 +74,11 @@ const Create = () => { ]) .then((result) => { const activeOauth = filter( - result[2].map((item:any)=>({ - ...item, + result[2].map((item: any) => ({ + ...item, platform_status: get(result[3], item.scm_platform_name, [false]), })), - 'platform_status' + 'platform_status', ); // HTTP 和 SSH ID可能重复 setSshAuthList(result[0]?.map((item: any) => ({ @@ -89,9 +89,9 @@ const Create = () => { ...item, authId: `${AUTH_TYPE.HTTP}#${item.id}`, }))); - setOauthAuthList(activeOauth.map((item:any)=>({ - ...item, - authId: `${AUTH_TYPE.OAUTH}#${item.id}`, + setOauthAuthList(activeOauth.map((item: any) => ({ + ...item, + authId: `${AUTH_TYPE.OAUTH}#${item.id}`, }))); }) .finally(() => { @@ -209,8 +209,8 @@ const Create = () => { rules={[ { required: true, message: t('请输入代码库地址') }, { - pattern: /(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/, - message: t('请输入合法的http代码库地址'), + pattern: /(https?):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/, + message: t('请输入合法的http代码库地址'), }, ]} > @@ -226,8 +226,8 @@ const Create = () => { shouldUpdate={(prevValues, curValues) => prevValues.scm_auth_id !== curValues.scm_auth_id} > {({ getFieldValue }) => { - const scmAuth = getFieldValue('scm_auth_id'); - return scmAuth?.startsWith('ssh_token') && ( + const scmAuth = getFieldValue('scm_auth_id'); + return scmAuth?.startsWith('ssh_token') && ( <> { - ); + ); }} { const history = useHistory(); - const { org_sid: orgSid, team_name: teamName }: any = useParams(); + const { orgSid, teamName }: any = useParams(); const { url } = useRouteMatch(); const { curRepo, repos } = useStateStore(); @@ -32,9 +32,9 @@ const Repos = () => { // // 存在登记的代码库,且repoId不存在或不在repos内则重定向到第一项 // if (!repoId || !repos.some((item: any) => item.id === repoId)) { // if (!repos.some((item: any) => item.id === curRepo.id)) { - // history.replace(getRepoRouter(org_sid, team_name, repos[0].id)); + // history.replace(getRepoRouter(orgSid, teamName, repos[0].id)); // } else { - // history.replace(getRepoRouter(org_sid, team_name, curRepo.id)); + // history.replace(getRepoRouter(orgSid, teamName, curRepo.id)); // } // } else { // // 存在repoId则直接采用该路由 @@ -42,14 +42,14 @@ const Repos = () => { // } else { // // 待移除 // // 未登记代码库,则重定向到欢迎页 - // history.replace(`${getReposRouter(org_sid, team_name)}/welcome`); + // history.replace(`${getReposRouter(orgSid, teamName)}/welcome`); // } // } // }; // useEffect(() => { // // 当处于xxx/repos路由时,进行重定向到对应代码库 - // if (!reposLoading && url === getReposRouter(org_sid, team_name)) { + // if (!reposLoading && url === getReposRouter(orgSid, teamName)) { // replaceToRepo(); // } // }); diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx index 8819ffd90..23ffc0247 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx @@ -6,6 +6,7 @@ import React, { useState } from 'react'; import { useParams, useHistory } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import classnames from 'classnames'; import { Row, Col, Tabs, Button, message } from 'coding-oa-uikit'; import LoadingIcon from 'coding-oa-uikit/lib/icon/Loading'; @@ -19,7 +20,6 @@ import { SET_REPOS } from '@src/context/constant'; import { useDispatchStore } from '@src/context/store'; import { getProjectRouter, getReposRouter } from '@src/utils/getRoutePath'; import { delRepo } from '@src/services/repos'; -import { t } from '@src/i18n/i18next'; import { useInitRepo } from '@src/modules/repos/hooks'; import LeftList from './left-list'; import Members from './tabs/members'; @@ -53,8 +53,9 @@ const getTabValue = () => { const RepoList = ({ repos }: IProps) => { const params: any = useParams(); + const { t } = useTranslation(); const repoId = toNumber(params.repoId); - const { org_sid: orgSid, team_name: teamName }: any = params; + const { orgSid, teamName }: any = params; const history = useHistory(); const dispatch = useDispatchStore(); const { curRepo, curRepoMember } = useInitRepo(orgSid, teamName, repoId); @@ -76,7 +77,7 @@ const RepoList = ({ repos }: IProps) => { const onDeleteRepo = () => { setDeleteVisible(true); }; - + const handleDeleteRepo = () => { delRepo(orgSid, teamName, repoId).then(() => { message.success('已删除代码库'); @@ -91,9 +92,10 @@ const RepoList = ({ repos }: IProps) => { } else { history.push(getReposRouter(orgSid, teamName)); } - }).finally(() => { - setDeleteVisible(false); - }); + }) + .finally(() => { + setDeleteVisible(false); + }); }; return ( diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx index e91bb5ced..92d0de88c 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx @@ -6,6 +6,7 @@ import React, { useState } from 'react'; import { Link, useParams, useHistory } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import classnames from 'classnames'; import { toNumber } from 'lodash'; @@ -16,7 +17,6 @@ import PlusIcon from 'coding-oa-uikit/lib/icon/Plus'; import GitBranchIcon from 'coding-oa-uikit/lib/icon/GitBranch'; import partnerIcon from '@src/images/partner.svg'; // 项目内 -import { t } from '@src/i18n/i18next'; import { getReposRouter } from '@src/utils/getRoutePath'; // 模块内 import s from './style.scss'; @@ -27,9 +27,10 @@ interface IProps { } const LeftList = ({ repos }: IProps) => { + const { t } = useTranslation(); const [searchValue, setSearchValue] = useState(''); const params: any = useParams(); - const { org_sid: orgSid, team_name: teamName }: any = params; + const { orgSid, teamName }: any = params; const repoId = toNumber(params.repoId); const history = useHistory(); diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss b/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss index e7f82f21a..e6ac12f1d 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .left-container { width: 300px; diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx index 31a61eaf2..76a7bad55 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx @@ -8,15 +8,14 @@ * 仓库登记入口文件 */ import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { find, isEmpty, get, filter } from 'lodash'; import { Button, Form, Select, message } from 'coding-oa-uikit'; import PlusIcon from 'coding-oa-uikit/lib/icon/Plus'; import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh'; // 项目内 -import { t } from '@src/i18n/i18next'; -import { SCM_PLATFORM } from '@src/common/constants'; -import { AUTH_TYPE, AUTH_TYPE_TXT } from '@src/modules/repos/constants'; +import { AUTH_TYPE, AUTH_TYPE_TXT, SCM_PLATFORM } from '@src/modules/repos/constants'; import { getPCAuthRouter } from '@src/modules/repos/routes'; import { getSSHInfo, getScmAccounts, putRepoAuth, getOAuthInfo, getPlatformStatus } from '@src/services/repos'; @@ -37,6 +36,7 @@ const layout = { * Todo: 目前仅存在http凭证,后续可能会添加各个oauth以及ssh等,后续再重新做其余认证模式处理 */ const Authority = ({ curRepo, orgSid, teamName, repoId }: IProps) => { + const { t } = useTranslation(); const [selectedAuth, setSelectedAuth] = useState({}); const [sshAuthList, setSshAuthList] = useState([]); const [httpAuthList, setHttpAuthList] = useState([]); @@ -58,7 +58,7 @@ const Authority = ({ curRepo, orgSid, teamName, repoId }: IProps) => { curAuth = scmAuth.scm_oauth; break; } - if(curAuth) { + if (curAuth) { curAuth.auth_type = curRepo?.scm_auth?.auth_type; } else { curAuth = {}; @@ -99,11 +99,11 @@ const Authority = ({ curRepo, orgSid, teamName, repoId }: IProps) => { getPlatformStatus().then(r => r || []), ]).then((result) => { const activeOauth = filter( - result[2].map((item:any)=>({ - ...item, + result[2].map((item: any) => ({ + ...item, platform_status: get(result[3], item.scm_platform_name, [false]), })), - 'platform_status' + 'platform_status', ); setSshAuthList(result[0]); setHttpAuthList(result[1]); diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx index baa90ddde..4ca0ba6f0 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx @@ -5,13 +5,13 @@ // ============================================================================== import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { unionWith, isEqual } from 'lodash'; import { Row, Col, Button, Avatar, Modal, Select, message } from 'coding-oa-uikit'; import PlusCircleIcon from 'coding-oa-uikit/lib/icon/PlusCircle'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; // 项目内 -import { t } from '@src/i18n/i18next'; import { useStateStore, useDispatchStore } from '@src/context/store'; import { SET_CUR_REPO_MEMBER } from '@src/context/constant'; import { getUserImgUrl } from '@src/utils'; @@ -38,7 +38,7 @@ const MemberItem = ({ list, title, onAddMemberClick }: IMemberItem) => ( {list.map((userinfo: any) => ( @@ -66,6 +66,7 @@ interface IProps { const Members = ({ orgSid, teamName, repoId, admins }: IProps) => { const dispatch = useDispatchStore(); + const { t } = useTranslation(); const [inviteVisb, setInviteVisb] = useState(false); const { projectMembers } = useStateStore(); const userOptions = unionWith(projectMembers.admins, projectMembers.users, isEqual).map(user => ({ diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx index edfaca826..fd3d3a07a 100644 --- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx +++ b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx @@ -5,11 +5,11 @@ // ============================================================================== import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { Form, Input, Button, message, Avatar } from 'coding-oa-uikit'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { merge } from 'lodash'; // 项目内 -import { t } from '@src/i18n/i18next'; import { formatDateTime, getUserImgUrl } from '@src/utils'; import { putRepo } from '@src/services/repos'; import { useDispatchStore } from '@src/context/store'; @@ -30,6 +30,7 @@ const layout = { const Overview = ({ curRepo, orgSid, teamName, repoId, deletable, onDelete }: IProps) => { const [form] = Form.useForm(); + const { t } = useTranslation(); const [edit, setEdit] = useState(false); const dispatch = useDispatchStore(); const creatorInfo = curRepo.creator || {}; diff --git a/web/packages/tca-analysis/src/modules/repos/routes.ts b/web/packages/tca-analysis/src/modules/repos/routes.ts index 5fb5a5881..2d8db1ad2 100644 --- a/web/packages/tca-analysis/src/modules/repos/routes.ts +++ b/web/packages/tca-analysis/src/modules/repos/routes.ts @@ -12,10 +12,10 @@ import { REPO_TAB_TYPE } from './constants'; * @param repoId 代码库ID */ export const getRepoRouter = ( - org_sid: string, - team_name: string, + orgSid: string, + teamName: string, repoId: number | string, tabKey: string = REPO_TAB_TYPE.MEMBER, -) => `${getBaseRouter(org_sid, team_name)}/repos/${repoId}/${tabKey}`; +) => `${getBaseRouter(orgSid, teamName)}/repos/${repoId}/${tabKey}`; export const getPCAuthRouter = () => '/user/auth'; diff --git a/web/packages/tca-analysis/src/modules/schemes/baseinfo/style.scss b/web/packages/tca-analysis/src/modules/schemes/baseinfo/style.scss index 19927ef66..c23bf5f7d 100644 --- a/web/packages/tca-analysis/src/modules/schemes/baseinfo/style.scss +++ b/web/packages/tca-analysis/src/modules/schemes/baseinfo/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .base-config { width: 670px; diff --git a/web/packages/tca-analysis/src/modules/schemes/branchs/index.tsx b/web/packages/tca-analysis/src/modules/schemes/branchs/index.tsx index 388b6bc2d..da2ee6fa4 100644 --- a/web/packages/tca-analysis/src/modules/schemes/branchs/index.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/branchs/index.tsx @@ -15,7 +15,7 @@ import { Table, Avatar } from 'coding-oa-uikit'; import UserIcon from 'coding-oa-uikit/lib/icon/User'; import { getBranchs } from '@src/services/schemes'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import commonStyle from '../style.scss'; import style from './style.scss'; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx index a11822f1e..cf734c213 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx @@ -12,7 +12,7 @@ import SelectBorderless from '@src/components/select-borderless'; import Filter from '@src/components/filter'; import { SEVERITY, CATEGORY } from '../constants'; -const numberParams = ['checkpackage', 'severity', 'category']; +const numberParams = ['checkpackage', 'severity', 'category', 'checktool']; const arrayParams = ['language']; interface SearchProps { @@ -25,13 +25,15 @@ interface SearchProps { const Search = (props: SearchProps) => { const [form] = Form.useForm(); const { searchParams, loading, filters, callback } = props; - const { allPkgs = [], languages = [] }: any = filters; + const { allPkgs = [], languages = [], checkTools = [] }: any = filters; const initialValues = cloneDeep(searchParams); Object.entries(initialValues).forEach(([key, value]: [string, string]) => { if (numberParams.includes(key) && isString(value)) { - initialValues[key] = value.split(',').map((item: string) => toNumber(item)); + initialValues[key] = value + .split(',') + .map((item: string) => toNumber(item)); } if (arrayParams.includes(key) && isString(value)) { @@ -61,70 +63,88 @@ const Search = (props: SearchProps) => { }; return ( - - - value && onChange('checkpackage', value.join(','))} - /> - - - ({ - value: toNumber(key), - text: value, - }))} - onChange={(value: any) => value && onChange('severity', value.join(','))} - /> - - - ({ - value: toNumber(key), - text: value, - }))} - onChange={(value: any) => value && onChange('category', value.join(','))} - /> - - - ({ - value: item.name, - text: item.display_name, - })) - } - onChange={(value: any) => value && onChange('language', value.join(','))} - /> - - - onChange('display_name', value)} - /> - - {Object.keys(searchParams).some((key: string) => ( - isArray(searchParams[key]) - ? !isEmpty(searchParams[key]) - : searchParams[key])) && ( - - )} - + + + value && onChange('checkpackage', value.join(',')) + } + /> + + + ({ + value: toNumber(key), + text: value, + }))} + onChange={(value: any) => value && onChange('severity', value.join(',')) + } + /> + + + ({ + value: toNumber(key), + text: value, + }))} + onChange={(value: any) => value && onChange('category', value.join(',')) + } + /> + + + ({ + value: item.id, + text: item.display_name, + }))} + onChange={(value: any) => value && onChange('checktool', value.join(',')) + } + /> + + + ({ + value: item.name, + text: item.display_name, + }))} + onChange={(value: any) => value && onChange('language', value.join(',')) + } + /> + + + onChange('real_name', value)} + /> + + {Object.keys(searchParams).some((key: string) => (isArray(searchParams[key]) + ? !isEmpty(searchParams[key]) + : searchParams[key])) && ( + + )} + ); }; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules.tsx index 1d8a2f598..bb3576705 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules.tsx @@ -17,13 +17,14 @@ import ArrowLeft from 'coding-oa-uikit/lib/icon/ArrowLeft'; import { getSchemeRouter } from '@src/utils/getRoutePath'; import { getQuery } from '@src/utils'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getAllRules, addRule, getRuleDetail, getAllCheckPackages, getLanguages, + getCheckTools, } from '@src/services/schemes'; import RuleDetail from '../../projects/issues/rule-detail'; @@ -36,7 +37,7 @@ const { Column } = Table; const AllRules = () => { const params: any = useParams(); const history = useHistory(); - const { org_sid: orgSid, team_name: teamName, repoId, schemeId } = params; + const { orgSid, teamName, repoId, schemeId } = params; const [list, setList] = useState([]); const [loading, setLoading] = useState(false); @@ -45,6 +46,7 @@ const AllRules = () => { const [selectedKeys, setSelectedKeys] = useState([]); const [ruleDetailVsb, setRuleDetailVsb] = useState(false); const [ruleDetail, setRuleDetail] = useState({}); + const [checkTools, setCheckTools] = useState([]); const [allPkgs, setAllPkgs] = useState([]); const [languages, setLanguages] = useState([]); @@ -80,8 +82,12 @@ const AllRules = () => { const list = res.results || []; history.push(`${window.location.pathname}?${qs.stringify(params)}`); - setSelectedKeys(list.filter((item: any) => item.select_state === 1).map((item: any) => item.id)); - setSelectedRowKeys(list.filter((item: any) => item.select_state === 1).map((item: any) => item.id)); + setSelectedKeys(list + .filter((item: any) => item.select_state === 1) + .map((item: any) => item.id)); + setSelectedRowKeys(list + .filter((item: any) => item.select_state === 1) + .map((item: any) => item.id)); setCount(res.count); setList(list); }) @@ -93,6 +99,12 @@ const AllRules = () => { useEffect(() => { getListData(); getAllPkgs(); + getCheckTools(orgSid, { + limit: 1000, + checkprofile_id: checkProfileId, + }).then((res: any) => { + setCheckTools(res.results || []); + }); (async () => { const resLanguages = await getLanguages(); @@ -124,85 +136,91 @@ const AllRules = () => { }; return ( -
-
- history.push(`${getSchemeRouter( - orgSid, - teamName, - repoId, - schemeId, - )}/check-profiles/${checkProfileId}/pkg/${pkgId}`) - } - > - - -
-

批量添加规则

-
-
- - { - getListData(DEFAULT_PAGER.pageStart, pageSize, params); - }} - /> - -
- {!isEmpty(difference(selectedRowKeys, selectedKeys)) && ( -
- -
- )} - item.id} - rowSelection={{ - selectedRowKeys, - onChange: keys => setSelectedRowKeys(keys), - getCheckboxProps: item => ({ disabled: item.select_state === 1 }), - }} - pagination={{ - current: Math.floor(pageStart / pageSize) + 1, - total: count, - pageSize, - showSizeChanger: true, - showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`, - onChange: onChangePageSize, - onShowSizeChange, - }} - > - ( -

openRuleDetail(data.id)}> - {name} -

- )} - /> - - - - -
-
- setRuleDetailVsb(false)} - data={ruleDetail} - /> +
+
+ history.push(`${getSchemeRouter( + orgSid, + teamName, + repoId, + schemeId, + )}/check-profiles/${checkProfileId}/pkg/${pkgId}`) + } + > + + +
+

批量添加规则

+
+ + { + getListData(DEFAULT_PAGER.pageStart, pageSize, params); + }} + /> + +
+ {!isEmpty(difference(selectedRowKeys, selectedKeys)) && ( +
+ +
+ )} + item.id} + rowSelection={{ + selectedRowKeys, + onChange: keys => setSelectedRowKeys(keys), + getCheckboxProps: item => ({ disabled: item.select_state === 1 }), + }} + pagination={{ + current: Math.floor(pageStart / pageSize) + 1, + total: count, + pageSize, + showSizeChanger: true, + showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`, + onChange: onChangePageSize, + onShowSizeChange, + }} + > + ( +

{ + openRuleDetail(data.id); + }} + > + {name} +

+ )} + /> + + + + +
+
+ setRuleDetailVsb(false)} + data={ruleDetail} + /> +
); }; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/compile-modal.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/compile-modal.tsx index 13efe003b..2f7fc8dd2 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-lint/compile-modal.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/compile-modal.tsx @@ -29,7 +29,9 @@ const CompileConfig = ({ visible, data, onOk, onClose }: CompileConfigProps) => visible={visible} onCancel={onClose} afterClose={() => form.resetFields()} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > { visible={visible} onCancel={onCancel} width={460} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > { - const { org_sid: orgSid, team_name: teamName, repoId, schemeId } = useParams() as any; + const { + orgSid, + teamName, + repoId, + schemeId, + } = useParams() as any; let { pkgId } = useParams() as any; const history = useHistory(); const location = useLocation(); @@ -72,7 +77,13 @@ const PkgRules = () => { }, [pkgId]); const getPkgDetail = async () => { - const res = await getCheckPackagesDetail(orgSid, teamName, repoId, schemeId, pkgId); + const res = await getCheckPackagesDetail( + orgSid, + teamName, + repoId, + schemeId, + pkgId, + ); setPkgDetail(res); }; @@ -81,7 +92,11 @@ const PkgRules = () => { setFilters(res); }; - const getListData = (offset = pageStart, limit = pageSize, otherParams = searchParams) => { + const getListData = ( + offset = pageStart, + limit = pageSize, + otherParams = searchParams, + ) => { const params = { offset, limit, @@ -132,7 +147,9 @@ const PkgRules = () => { Modal.confirm({ title: `${text}规则`, - content: `您正在${text} ${keys.length} 条规则,${text}后, 在代码分析过程中将${ + content: `您正在${text} ${ + keys.length + } 条规则,${text}后, 在代码分析过程中将${ state === 2 ? '忽略' : '启用' }这些规则,确定${text}?`, onOk: () => { @@ -185,211 +202,225 @@ const PkgRules = () => { }; return ( -
-
- history.push(`${getSchemeRouter(orgSid, teamName, repoId, schemeId)}/codelint`) - } - > - - -
-

{isCustomPkg ? '自定义规则包' : pkgDetail.name}

-

- {isCustomPkg - ? '自定义规则包中规则配置会默认覆盖其他官方包中相同规则的配置' - : pkgDetail.description} -

-
- {isCustomPkg && ( - - )} -
+
+
+ history.push(`${getSchemeRouter(orgSid, teamName, repoId, schemeId)}/codelint`) + } + > + + +
+

+ {isCustomPkg ? '自定义规则包' : pkgDetail.name} +

+

+ {isCustomPkg + ? '自定义规则包中规则配置会默认覆盖其他官方包中相同规则的配置' + : pkgDetail.description} +

+
+ {isCustomPkg && ( + + )} +
- { - getListData(DEFAULT_PAGER.pageStart, pageSize, params); + { + getListData(DEFAULT_PAGER.pageStart, pageSize, params); + }} + /> +
+ {!isEmpty(selectedRowKeys) && ( +
+ + {isCustomPkg ? ( + + ) : ( + <> + + + + )} +
+ )} + item.id} + rowSelection={{ + selectedRowKeys, + onChange: keys => setSelectedRowKeys(keys), + }} + pagination={{ + current: Math.floor(pageStart / pageSize) + 1, + total: count, + pageSize, + showSizeChanger: true, + showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`, + onChange: onChangePageSize, + onShowSizeChange, + }} + > + ( +

{ + openRuleDetail(get(data, 'checkrule.id')); }} - /> -

- {!isEmpty(selectedRowKeys) && ( -
- - {isCustomPkg ? ( - - ) : ( - <> - - - - )} -
+ > + {data.state === 2 && ( + (已屏蔽) )} -
item.id} - rowSelection={{ - selectedRowKeys, - onChange: keys => setSelectedRowKeys(keys), + {name} +

+ )} + /> + + + { + const value = data.rule_params || params; + return value && value.length > 30 ? ( + +

{value}

+
+ ) : ( + value + ); + }} + /> + + SEVERITY[data.severity || severity] + } + /> + ( + <> + { + setEditRule({ + data: item, + visible: true, + }); + }} + > + 编辑 + + {isCustomPkg ? ( + { + setSelectedRowKeys([id]); + delRules([id]); }} - pagination={{ - current: Math.floor(pageStart / pageSize) + 1, - total: count, - pageSize, - showSizeChanger: true, - showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`, - onChange: onChangePageSize, - onShowSizeChange, + > + 移除 + + ) : ( + { + setSelectedRowKeys([id]); + ruleStateHandle(item.state === 2 ? 1 : 2, [id]); }} - > - ( -

openRuleDetail(get(data, 'checkrule.id'))} - > - {data.state === 2 && ( - (已屏蔽) - )} - {name} -

- )} - /> - - { - const value = data.rule_params || params; - return value && value.length > 30 ? ( - -

{value}

-
- ) : ( - value - ); - }} - /> - - SEVERITY[data.severity || severity]} - /> - ( - <> -
{ - setEditRule({ - data: item, - visible: true, - }); - }} - > - 编辑 - - {isCustomPkg ? ( - { - setSelectedRowKeys([id]); - delRules([id]); - }} - > - 移除 - - ) : ( - { - setSelectedRowKeys([id]); - ruleStateHandle(item.state === 2 ? 1 : 2, [id]); - }} - > - {item.state === 2 ? '取消屏蔽' : '屏蔽'} - - )} - - )} - /> -
-
- setBatchModalVsb(false)} - onOk={ruleSeverityHandle} - > -

- 已选定 {selectedRowKeys.length} 个规则,将其严重级别统一修改为: -

- setSeverity(e.target.value)}> - {Object.keys(SEVERITY).map((key: any) => ( - - {SEVERITY[key]} - - ))} - -
- setRuleDetailVsb(false)} - data={ruleDetail} - /> - setEditRule({ visible: false, data: {} })} - callback={() => getListData(pageStart, pageSize)} - /> -
+ > + {item.state === 2 ? '取消屏蔽' : '屏蔽'} + + )} + + )} + /> + +
+ setBatchModalVsb(false)} + onOk={ruleSeverityHandle} + > +

+ 已选定 {selectedRowKeys.length} 个规则,将其严重级别统一修改为: +

+ setSeverity(e.target.value)}> + {Object.keys(SEVERITY).map((key: any) => ( + + {SEVERITY[key]} + + ))} + +
+ setRuleDetailVsb(false)} + data={ruleDetail} + /> + setEditRule({ visible: false, data: {} })} + callback={() => getListData(pageStart, pageSize)} + /> +
); }; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/search.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/search.tsx index 5f4f61f52..de7200943 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-lint/search.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/search.tsx @@ -11,7 +11,7 @@ import { Input, Form, Button } from 'coding-oa-uikit'; import SelectBorderless from '@src/components/select-borderless'; import Filter from '@src/components/filter'; -const numberParams = ['checkrule_category', 'severity']; +const numberParams = ['checkrule_category', 'severity', 'checktool']; const arrayParams = ['checkrule_language']; interface SearchProps { @@ -28,13 +28,16 @@ const Search = (props: SearchProps) => { checkrule_category: category = [], checkrule_language: language = [], severity = [], + checktool = [], } = filters as any; const initialValues = cloneDeep(searchParams); Object.entries(initialValues).forEach(([key, value]: [string, string]) => { if (numberParams.includes(key) && isString(value)) { - initialValues[key] = value.split(',').map((item: string) => toNumber(item)); + initialValues[key] = value + .split(',') + .map((item: string) => toNumber(item)); } if (arrayParams.includes(key) && isString(value)) { @@ -64,52 +67,66 @@ const Search = (props: SearchProps) => { }; return ( - - - value && onChange('severity', value.join(','))} - /> - - - value && onChange('checkrule_category', value.join(',')) - } - /> - - - value && onChange('checkrule_language', value.join(',')) - } - /> - - - onChange('checkrule_name', value)} - /> - - {Object.keys(searchParams).some((key: string) => ( - isArray(searchParams[key]) - ? !isEmpty(searchParams[key]) - : searchParams[key])) && ( - - )} - + + + value && onChange('severity', value.join(',')) + } + /> + + + value && onChange('checkrule_category', value.join(',')) + } + /> + + + value && onChange('checktool', value.join(',')) + } + /> + + + value && onChange('checkrule_language', value.join(',')) + } + /> + + + onChange('checkrule_name', value)} + /> + + {Object.keys(searchParams).some((key: string) => (isArray(searchParams[key]) + ? !isEmpty(searchParams[key]) + : searchParams[key])) && ( + + )} + ); }; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/style.scss b/web/packages/tca-analysis/src/modules/schemes/code-lint/style.scss index ceef2ee86..5ef7a1302 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-lint/style.scss +++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/style.scss @@ -1,4 +1,4 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .code-lint { padding-top: 30px; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-metrics/index.tsx b/web/packages/tca-analysis/src/modules/schemes/code-metrics/index.tsx index c235429ec..ccd785077 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-metrics/index.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/code-metrics/index.tsx @@ -21,56 +21,56 @@ import style from './style.scss'; import formStyle from '../style.scss'; const defaultValues = { - min_ccn: 20, - dup_block_length_min: 120, - dup_min_dup_times: 2, - dup_issue_limit: 1000, + min_ccn: 20, + dup_block_length_min: 120, + dup_min_dup_times: 2, + dup_issue_limit: 1000, }; const layout = { - labelCol: { span: 5 }, - wrapperCol: { span: 19 }, + labelCol: { span: 5 }, + wrapperCol: { span: 19 }, }; interface CodeMetricsProps { - repoId: number; - schemeId: number; - orgSid: string; - teamName: string; + repoId: number; + schemeId: number; + orgSid: string; + teamName: string; } const CodeMetrics = (props: CodeMetricsProps) => { - const { orgSid, teamName, repoId, schemeId } = props; - const [form] = Form.useForm(); - const [data, setData] = useState({}); - - useEffect(() => { - getCodeMetrics(orgSid, teamName, repoId, schemeId).then((response: any) => { - setData(response); - form.resetFields(); - }); - }, [schemeId]); - - const update = (formData: any, info: string) => { - updateCodeMetrics(orgSid, teamName, repoId, schemeId, { - ...data, - ...formData, - }).then((response: any) => { - message.success(`${info}成功`); - setData(response); - form.resetFields(); - }); - }; - - const onFinish = (formData: any) => { - update({ - ...formData, - ...defaultValues, - ...pickBy(formData, key => isNumber(key)), - }, '更新'); - }; - - return ( + const { orgSid, teamName, repoId, schemeId } = props; + const [form] = Form.useForm(); + const [data, setData] = useState({}); + + useEffect(() => { + getCodeMetrics(orgSid, teamName, repoId, schemeId).then((response: any) => { + setData(response); + form.resetFields(); + }); + }, [schemeId]); + + const update = (formData: any, info: string) => { + updateCodeMetrics(orgSid, teamName, repoId, schemeId, { + ...data, + ...formData, + }).then((response: any) => { + message.success(`${info}成功`); + setData(response); + form.resetFields(); + }); + }; + + const onFinish = (formData: any) => { + update({ + ...formData, + ...defaultValues, + ...pickBy(formData, key => isNumber(key)), + }, '更新'); + }; + + return ( { size='small' checked={data.cc_scan_enabled} onChange={(checked: boolean) => update({ - cc_scan_enabled: checked, + cc_scan_enabled: checked, }, `圈复杂度${checked ? '开启' : '关闭'}`)} />
@@ -134,7 +134,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { size='small' checked={data.dup_scan_enabled} onChange={(checked: boolean) => update({ - dup_scan_enabled: checked, + dup_scan_enabled: checked, }, `重复代码${checked ? '开启' : '关闭'}`)} /> @@ -232,7 +232,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { size='small' checked={data.cloc_scan_enabled} onChange={(checked: boolean) => update({ - cloc_scan_enabled: checked, + cloc_scan_enabled: checked, }, `代码统计${checked ? '开启' : '关闭'}`)} /> @@ -242,7 +242,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { - ); + ); }; export default CodeMetrics; diff --git a/web/packages/tca-analysis/src/modules/schemes/code-metrics/style.scss b/web/packages/tca-analysis/src/modules/schemes/code-metrics/style.scss index 99e78d752..856ac3c48 100644 --- a/web/packages/tca-analysis/src/modules/schemes/code-metrics/style.scss +++ b/web/packages/tca-analysis/src/modules/schemes/code-metrics/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .code-metrics { width: 700px; diff --git a/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx b/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx index 1eca2c699..46484e06c 100644 --- a/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx @@ -49,6 +49,8 @@ const CreatSchemeModal = (props: IProps) => { if (data.createType === 'create') { const { funcList = [] } = data; + // 开源版需要隐藏tag,默认赋予tag Codedog_Linux + const tag = tags.filter(item => item.public && item.name === 'Codedog_Linux').pop() || tags.pop(); createScheme(orgSid, teamName, repoId, { ...pick(data, ['name', 'languages', 'tag']), ...SCAN_LIST.map(item => ({ [item.value]: funcList.includes(item.value) })).reduce( @@ -59,6 +61,7 @@ const CreatSchemeModal = (props: IProps) => { envs: null, pre_cmd: null, name: trim(data.name), + tag: tag.name || 'Codedog_Linux', }).then((res) => { message.success('创建成功'); callback(res.scan_scheme); @@ -83,7 +86,9 @@ const CreatSchemeModal = (props: IProps) => { visible={visible} onCancel={onClose} afterClose={() => form.resetFields()} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} >
{ const tab = params.tabs || 'basic'; const schemeId = toNumber(params.schemeId); - const { org_sid: orgSid, team_name: teamName } = params; + const { orgSid, teamName } = params; useEffect(() => { getCommonData(); @@ -120,7 +120,9 @@ const Schemes = () => { addSchemeHandle={() => { setVisible(true); }} - changeSchemeHandle={item => getSchemeInfo(item.id)} + changeSchemeHandle={(item) => { + getSchemeInfo(item.id); + }} />
@@ -252,7 +254,9 @@ const Schemes = () => { schemeId={schemeInfo.id} visible={pullModalVsb} onClose={() => setPullModalVsb(false)} - callback={(id: number | string) => getSchemeInfo(id)} + callback={(id: number | string) => { + getSchemeInfo(id); + }} />
); diff --git a/web/packages/tca-analysis/src/modules/schemes/path-filter/index.tsx b/web/packages/tca-analysis/src/modules/schemes/path-filter/index.tsx index 6a7cadda1..9d4c1af8f 100644 --- a/web/packages/tca-analysis/src/modules/schemes/path-filter/index.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/path-filter/index.tsx @@ -19,7 +19,7 @@ import { getScanDir, } from '@src/services/schemes'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import Branch from './branch'; import Path from './path'; diff --git a/web/packages/tca-analysis/src/modules/schemes/path-filter/modal.tsx b/web/packages/tca-analysis/src/modules/schemes/path-filter/modal.tsx index 1fdeb1781..2eea5c21c 100644 --- a/web/packages/tca-analysis/src/modules/schemes/path-filter/modal.tsx +++ b/web/packages/tca-analysis/src/modules/schemes/path-filter/modal.tsx @@ -48,7 +48,9 @@ const UpdateModal = (props: IProps) => { width={520} className={style.addPathModal} okText={isEditModal ? '确定' : '添加'} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > { const [form] = Form.useForm(); const { searchParams, loading, filters, callback } = props; - const { allPkgs = [], languages = [] } = filters as any; + const { allPkgs = [], labels = [], languages = [], checkTools = [] } = filters as any; const initialValues = cloneDeep(searchParams); Object.entries(initialValues).forEach(([key, value]: [string, string]) => { if (numberParams.includes(key) && isString(value)) { - initialValues[key] = value.split(',').map((item: string) => toNumber(item)); + initialValues[key] = value + .split(',') + .map((item: string) => toNumber(item)); } if (arrayParams.includes(key) && isString(value)) { @@ -61,14 +63,19 @@ const Search = (props: SearchProps) => { }; return ( - + value && onChange('checkpackage', value.join(','))} + onChange={(value: any) => value && onChange('checkpackage', value.join(',')) + } /> @@ -80,7 +87,8 @@ const Search = (props: SearchProps) => { value: toNumber(key), text: value, }))} - onChange={(value: any) => value && onChange('severity', value.join(','))} + onChange={(value: any) => value && onChange('severity', value.join(',')) + } /> @@ -88,11 +96,22 @@ const Search = (props: SearchProps) => { multiple allowClear placeholder="全部" - data={Object.entries(CATEGORY).map(([key, value]: [string, string]) => ({ - value: toNumber(key), - text: value, + data={getData(labels)} + onChange={(value: any) => value && onChange('category', value.join(',')) + } + /> + + + ({ + value: item.id, + text: item.display_name, }))} - onChange={(value: any) => value && onChange('category', value.join(','))} + onChange={(value: any) => value && onChange('checktool', value.join(',')) + } /> @@ -100,31 +119,28 @@ const Search = (props: SearchProps) => { multiple allowClear placeholder="全部" - data={ - languages?.map((item: any) => ({ - value: item.name, - text: item.display_name, - })) + data={languages?.map((item: any) => ({ + value: item.name, + text: item.display_name, + }))} + onChange={(value: any) => value && onChange('language_name', value.join(',')) } - onChange={(value: any) => value && onChange('language_name', value.join(','))} /> - + onChange('display_name', value)} + onSearch={value => onChange('real_name', value)} /> - { - Object.keys(searchParams).some((key: string) => ( - isArray(searchParams[key]) - ? !isEmpty(searchParams[key]) - : searchParams[key])) && ( - - )} + {Object.keys(searchParams).some((key: string) => (isArray(searchParams[key]) + ? !isEmpty(searchParams[key]) + : searchParams[key])) && ( + + )} ); }; diff --git a/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx b/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx index 769bbc860..116d26160 100644 --- a/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx +++ b/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx @@ -17,14 +17,14 @@ import ArrowLeft from 'coding-oa-uikit/lib/icon/ArrowLeft'; import { getTmplRouter } from '@src/utils/getRoutePath'; import { getQuery } from '@src/utils'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getAllRules, addRule, getRuleDetail, getAllCheckPackages, } from '@src/services/template'; -import { getLanguages } from '@src/services/schemes'; +import { getLabels, getLanguages, getCheckTools } from '@src/services/schemes'; import RuleDetail from '../../projects/issues/rule-detail'; import Search from './all-rules-search'; @@ -44,8 +44,10 @@ const AllRules = () => { const [selectedKeys, setSelectedKeys] = useState([]); const [ruleDetailVsb, setRuleDetailVsb] = useState(false); const [ruleDetail, setRuleDetail] = useState({}); + const [checkTools, setCheckTools] = useState([]); const [allPkgs, setAllPkgs] = useState([]); + const [labels, setLabels] = useState([]); const [languages, setLanguages] = useState([]); const query = getQuery(); @@ -55,21 +57,29 @@ const AllRules = () => { const checkProfileId = toNumber(params.checkProfileId); const pkgId = toNumber(params.pkgId); - const { org_sid: orgSid, team_name: teamName, id: tmplId } = params; + const { orgSid, teamName, id: tmplId } = params; useEffect(() => { getListData(); getAllPkgs(); + getCheckTools(orgSid, { + limit: 1000, + checkprofile_id: checkProfileId, + }).then((res: any) => { + setCheckTools(res.results || []); + }); (async () => { + const labels = await getLabels(); const languages = await getLanguages(); + setLabels(labels.results || []); setLanguages(languages.results || []); })(); }, [pkgId]); const getAllPkgs = async () => { let pkgs = await getAllCheckPackages(orgSid, tmplId); - pkgs = (pkgs || []).filter((item: any) => !item.disable); + pkgs = (pkgs.results || []).filter((item: any) => !item.disable); setAllPkgs(pkgs); }; @@ -90,8 +100,12 @@ const AllRules = () => { const list = res.results || []; history.push(`${location.pathname}?${qs.stringify(params)}`); - setSelectedKeys(list.filter((item: any) => item.select_state === 1).map((item: any) => item.id)); - setSelectedRowKeys(list.filter((item: any) => item.select_state === 1).map((item: any) => item.id)); + setSelectedKeys(list + .filter((item: any) => item.select_state === 1) + .map((item: any) => item.id)); + setSelectedRowKeys(list + .filter((item: any) => item.select_state === 1) + .map((item: any) => item.id)); setCount(res.count); setList(list); }) @@ -128,7 +142,9 @@ const AllRules = () => {
history.push(`${getTmplRouter(orgSid, teamName)}/${params.id}/check-profiles/${checkProfileId}/pkg/${pkgId}`) + onClick={() => history.push(`${getTmplRouter(orgSid, teamName)}/${ + params.id + }/check-profiles/${checkProfileId}/pkg/${pkgId}`) } > @@ -141,7 +157,9 @@ const AllRules = () => { { > ( -

openRuleDetail(data.id)}> +

{ + openRuleDetail(data.id); + }} + > {name}

)} /> - + diff --git a/web/packages/tca-analysis/src/modules/template/code-lint/edit-rule-modal.tsx b/web/packages/tca-analysis/src/modules/template/code-lint/edit-rule-modal.tsx index 04b0fd0cc..711e16ad3 100644 --- a/web/packages/tca-analysis/src/modules/template/code-lint/edit-rule-modal.tsx +++ b/web/packages/tca-analysis/src/modules/template/code-lint/edit-rule-modal.tsx @@ -16,7 +16,7 @@ import { SEVERITY } from '../../schemes/constants'; import { modifyRule } from '@src/services/template'; interface EditRuleModalProps { - org_sid: string; + orgSid: string; tmplId: number; checkProfileId: number; visible: boolean; @@ -27,7 +27,7 @@ interface EditRuleModalProps { const EditRuleModal = (props: EditRuleModalProps) => { const [form] = Form.useForm(); - const { org_sid: orgSid, tmplId, data, visible, onCancel, callback } = props; + const { orgSid, tmplId, data, visible, onCancel, callback } = props; useEffect(() => { visible && form.resetFields(); @@ -52,7 +52,9 @@ const EditRuleModal = (props: EditRuleModalProps) => { visible={visible} onCancel={onCancel} width={460} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > { - const { org_sid: orgSid, team_name: teamName, id: tmplId } = useParams() as any; + const { + orgSid, + teamName, + id: tmplId, + } = useParams() as any; let { checkProfileId, pkgId } = useParams() as any; const history = useHistory(); const location = useLocation(); @@ -90,7 +94,11 @@ const PkgRules = () => { setFilters(res); }; - const getListData = (offset = pageStart, limit = pageSize, otherParams = searchParams) => { + const getListData = ( + offset = pageStart, + limit = pageSize, + otherParams = searchParams, + ) => { const params = { offset, limit, @@ -141,7 +149,10 @@ const PkgRules = () => { Modal.confirm({ title: `${text}规则`, - content: `您正在${text} ${keys.length} 条规则,${text}后, 在代码分析过程中将${state === 2 ? '忽略' : '启用' + content: `您正在${text} ${ + keys.length + } 条规则,${text}后, 在代码分析过程中将${ + state === 2 ? '忽略' : '启用' }这些规则,确定${text}?`, onOk: () => { modifyRuleState(orgSid, tmplId, { @@ -197,12 +208,15 @@ const PkgRules = () => {
history.push(`${getTmplRouter(orgSid, teamName)}/${tmplId}/codelint`)} + onClick={() => history.push(`${getTmplRouter(orgSid, teamName)}/${tmplId}/codelint`) + } >
-

{isCustomPkg ? '自定义规则包' : pkgDetail.name}

+

+ {isCustomPkg ? '自定义规则包' : pkgDetail.name} +

{isCustomPkg ? '自定义规则包中规则配置会默认覆盖其他官方包中相同规则的配置' @@ -238,7 +252,7 @@ const PkgRules = () => { style={{ marginRight: 10 }} > 修改严重级别 - + {isCustomPkg ? ( ) : ( - <> - - - + <> + + + )}

)} @@ -290,11 +304,13 @@ const PkgRules = () => { (

openRuleDetail(get(data, 'checkrule.id'))} + onClick={() => { + openRuleDetail(get(data, 'checkrule.id')); + }} > {data.state === 2 && ( (已屏蔽) @@ -303,7 +319,12 @@ const PkgRules = () => {

)} /> - + + { ); }} /> - + SEVERITY[data.severity || severity]} + render={(severity, data: any) => SEVERITY[data.severity || severity] + } /> {!isSysTmpl && ( { }} > 编辑 - + {isCustomPkg ? ( { 移除 ) : ( - { - setSelectedRowKeys([id]); - ruleStateHandle(item.state === 2 ? 1 : 2, [id]); - }} - > - {item.state === 2 ? '取消屏蔽' : '屏蔽'} - + { + setSelectedRowKeys([id]); + ruleStateHandle(item.state === 2 ? 1 : 2, [id]); + }} + > + {item.state === 2 ? '取消屏蔽' : '屏蔽'} + )} )} @@ -378,7 +404,7 @@ const PkgRules = () => { >

已选定 {selectedRowKeys.length} 个规则,将其严重级别统一修改为: -

+

setSeverity(e.target.value)}> {Object.keys(SEVERITY).map((key: any) => ( @@ -393,7 +419,7 @@ const PkgRules = () => { data={ruleDetail} /> { checkrule_category: category = [], checkrule_language: language = [], severity = [], + checktool = [], } = filters as any; const initialValues = cloneDeep(searchParams); Object.entries(initialValues).forEach(([key, value]: [string, string]) => { if (numberParams.includes(key) && isString(value)) { - initialValues[key] = value.split(',').map((item: string) => toNumber(item)); + initialValues[key] = value + .split(',') + .map((item: string) => toNumber(item)); } if (arrayParams.includes(key) && isString(value)) { @@ -64,53 +67,66 @@ const Search = (props: SearchProps) => { }; return ( - - - value && onChange('severity', value.join(','))} - /> - - - value && onChange('checkrule_category', value.join(',')) - } - /> - - - value && onChange('checkrule_language', value.join(',')) - } - /> - - - onChange('checkrule_name', value)} - /> - - { - Object.keys(searchParams).some((key: string) => ( - isArray(searchParams[key]) - ? !isEmpty(searchParams[key]) - : searchParams[key])) && ( - - )} - + + + value && onChange('severity', value.join(',')) + } + /> + + + value && onChange('checkrule_category', value.join(',')) + } + /> + + + value && onChange('checktool', value.join(',')) + } + /> + + + value && onChange('checkrule_language', value.join(',')) + } + /> + + + onChange('checkrule_name', value)} + /> + + {Object.keys(searchParams).some((key: string) => (isArray(searchParams[key]) + ? !isEmpty(searchParams[key]) + : searchParams[key])) && ( + + )} + ); }; diff --git a/web/packages/tca-analysis/src/modules/template/code-lint/style.scss b/web/packages/tca-analysis/src/modules/template/code-lint/style.scss index c2e48ba15..6dae231e7 100644 --- a/web/packages/tca-analysis/src/modules/template/code-lint/style.scss +++ b/web/packages/tca-analysis/src/modules/template/code-lint/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .code-lint { padding-top: 30px; diff --git a/web/packages/tca-analysis/src/modules/template/code-metrics/index.tsx b/web/packages/tca-analysis/src/modules/template/code-metrics/index.tsx index 5d16e0cc7..72685d981 100644 --- a/web/packages/tca-analysis/src/modules/template/code-metrics/index.tsx +++ b/web/packages/tca-analysis/src/modules/template/code-metrics/index.tsx @@ -21,82 +21,82 @@ import style from './style.scss'; import formStyle from '../style.scss'; const defaultValues = { - min_ccn: 20, - dup_block_length_min: 120, - dup_min_dup_times: 2, - dup_issue_limit: 1000, + min_ccn: 20, + dup_block_length_min: 120, + dup_min_dup_times: 2, + dup_issue_limit: 1000, }; const layout = { - labelCol: { span: 5 }, - wrapperCol: { span: 19 }, + labelCol: { span: 5 }, + wrapperCol: { span: 19 }, }; interface CodeMetricsProps { - orgSid: string; - tmplId: number; - isSysTmpl: boolean; + orgSid: string; + tmplId: number; + isSysTmpl: boolean; } const CodeMetrics = (props: CodeMetricsProps) => { - const { orgSid, tmplId, isSysTmpl } = props; - const [form] = Form.useForm(); - const [data, setData] = useState({}); - const [visible, setVisible] = useState(false); - const [formData, setFormData] = useState({}); + const { orgSid, tmplId, isSysTmpl } = props; + const [form] = Form.useForm(); + const [data, setData] = useState({}); + const [visible, setVisible] = useState(false); + const [formData, setFormData] = useState({}); - useEffect(() => { - getTmplMetrics(orgSid, tmplId).then((response: any) => { - setData(response); - form.resetFields(); - }); - }, [tmplId]); + useEffect(() => { + getTmplMetrics(orgSid, tmplId).then((response: any) => { + setData(response); + form.resetFields(); + }); + }, [tmplId]); - const update = (formData: any, info: string, callback?: any) => { - updateTmplMetrics(orgSid, tmplId, { - ...data, - ...formData, - }).then((response: any) => { - setData(response); - form.resetFields(); + const update = (formData: any, info: string, callback?: any) => { + updateTmplMetrics(orgSid, tmplId, { + ...data, + ...formData, + }).then((response: any) => { + setData(response); + form.resetFields(); - if (callback) { - callback(); - } else { - message.success(`${info}成功`); - } - }); - }; + if (callback) { + callback(); + } else { + message.success(`${info}成功`); + } + }); + }; - const onFinish = (data: any) => { - setVisible(true); - setFormData(data); - }; + const onFinish = (data: any) => { + setVisible(true); + setFormData(data); + }; - const onSync = (keys: any) => { - update({ - ...formData, - ...defaultValues, - ...pickBy(formData, key => isNumber(key)), - }, '更新', () => { - if (keys.length === 0) { - setVisible(false); - message.success('更新成功'); - } - }); + const onSync = (keys: any) => { + update({ + ...formData, + ...defaultValues, + ...pickBy(formData, key => isNumber(key)), + }, '更新', () => { + if (keys.length === 0) { + setVisible(false); + message.success('更新成功'); + } + }); - if (keys.length > 0) { - syncScheme(orgSid, tmplId, { - sync_metric_conf: true, - schemes: keys, - }).then(() => { - message.success('同步成功'); - setVisible(false); - }); - } - }; + if (keys.length > 0) { + syncScheme(orgSid, tmplId, { + sync_metric_conf: true, + schemes: keys, + }).then(() => { + message.success('同步成功'); + setVisible(false); + }); + } + }; - return ( + return ( <> { disabled={isSysTmpl} checked={data.cc_scan_enabled} onChange={(checked: boolean) => update({ - cc_scan_enabled: checked, + cc_scan_enabled: checked, }, `圈复杂度${checked ? '开启' : '关闭'}`)} /> @@ -163,7 +163,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { size='small' checked={data.dup_scan_enabled} onChange={(checked: boolean) => update({ - dup_scan_enabled: checked, + dup_scan_enabled: checked, }, `重复代码${checked ? '开启' : '关闭'}`)} /> @@ -266,7 +266,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { size='small' checked={data.cloc_scan_enabled} onChange={(checked: boolean) => update({ - cloc_scan_enabled: checked, + cloc_scan_enabled: checked, }, `代码统计${checked ? '开启' : '关闭'}`)} /> @@ -290,7 +290,7 @@ const CodeMetrics = (props: CodeMetricsProps) => { ) } - ); + ); }; export default CodeMetrics; diff --git a/web/packages/tca-analysis/src/modules/template/code-metrics/style.scss b/web/packages/tca-analysis/src/modules/template/code-metrics/style.scss index 99e78d752..856ac3c48 100644 --- a/web/packages/tca-analysis/src/modules/template/code-metrics/style.scss +++ b/web/packages/tca-analysis/src/modules/template/code-metrics/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .code-metrics { width: 700px; diff --git a/web/packages/tca-analysis/src/modules/template/create.tsx b/web/packages/tca-analysis/src/modules/template/create.tsx index 2af63e088..468e74d79 100644 --- a/web/packages/tca-analysis/src/modules/template/create.tsx +++ b/web/packages/tca-analysis/src/modules/template/create.tsx @@ -37,6 +37,8 @@ const CreatSchemeModal = (props: IProps) => { const onFinish = (data: any) => { const { funcList = [] } = data; + // 开源版需要隐藏tag,默认赋予tag Codedog_Linux + const tag = tags.filter(item => item.public && item.name === 'Codedog_Linux').pop() || tags.pop(); createTmpl(orgSid, { ...pick(data, ['name', 'languages', 'tag', 'description']), ...SCAN_LIST.map(item => ({ [item.value]: funcList.includes(item.value) })).reduce( @@ -47,6 +49,8 @@ const CreatSchemeModal = (props: IProps) => { envs: null, pre_cmd: null, name: trim(data.name), + // 开源版需要隐藏tag,默认赋予tag Codedog_Linux + tag: tag.name || 'Codedog_Linux', }).then((res: any) => { message.success('创建成功'); onReset(); @@ -66,7 +70,9 @@ const CreatSchemeModal = (props: IProps) => { className={style.schemeCreateModal} visible={visible} onCancel={onReset} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} > { const history = useHistory(); const params: any = useParams(); - const { org_sid: orgSid, team_name: teamName }: any = params; + const { orgSid, teamName }: any = params; const [loading, setLoading] = useState(false); const [data, setData] = useState({}) as any; diff --git a/web/packages/tca-analysis/src/modules/template/index.tsx b/web/packages/tca-analysis/src/modules/template/index.tsx index ffd4958fc..2961911ed 100644 --- a/web/packages/tca-analysis/src/modules/template/index.tsx +++ b/web/packages/tca-analysis/src/modules/template/index.tsx @@ -16,7 +16,7 @@ import qs from 'qs'; import { Table, Tag } from 'coding-oa-uikit'; import { getQuery } from '@src/utils'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import { getTmplList } from '@src/services/template'; import { getLanguages, getTags } from '@src/services/schemes'; @@ -28,7 +28,7 @@ const { Column } = Table; const Template = () => { const history = useHistory(); - const { org_sid: orgSid } = useParams() as any; + const { orgSid } = useParams() as any; const [list, setList] = useState([]); const [count, setCount] = useState(DEFAULT_PAGER.count); const [loading, setLoading] = useState(false); diff --git a/web/packages/tca-analysis/src/modules/template/path-filter/index.tsx b/web/packages/tca-analysis/src/modules/template/path-filter/index.tsx index 97129a9e5..b20d265bc 100644 --- a/web/packages/tca-analysis/src/modules/template/path-filter/index.tsx +++ b/web/packages/tca-analysis/src/modules/template/path-filter/index.tsx @@ -27,7 +27,7 @@ import { syncScheme, } from '@src/services/template'; -import { DEFAULT_PAGER } from '@src/common/constants'; +import { DEFAULT_PAGER } from '@src/constant'; import List from './list'; import PathOperation from './path-operation'; diff --git a/web/packages/tca-analysis/src/modules/template/path-filter/modal.tsx b/web/packages/tca-analysis/src/modules/template/path-filter/modal.tsx index 09049e5f6..f87fe0ac4 100644 --- a/web/packages/tca-analysis/src/modules/template/path-filter/modal.tsx +++ b/web/packages/tca-analysis/src/modules/template/path-filter/modal.tsx @@ -48,7 +48,9 @@ const UpdateModal = (props: IProps) => { width={520} className={style.addPathModal} okText={isEditModal ? '确定' : '添加'} - onOk={() => form.validateFields().then(onFinish)} + onOk={() => { + form.validateFields().then(onFinish); + }} // afterClose={() => form.resetFields()} > { - const { org_sid: orgSid, team_name: teamName } = useParams() as any; + const { orgSid, teamName } = useParams() as any; const { onlySync, visible, tmplId, onClose, onOk } = props; const [list, setList] = useState([]); diff --git a/web/packages/tca-analysis/src/modules/welcome/index.tsx b/web/packages/tca-analysis/src/modules/welcome/index.tsx index bdc294b91..b2ced797b 100644 --- a/web/packages/tca-analysis/src/modules/welcome/index.tsx +++ b/web/packages/tca-analysis/src/modules/welcome/index.tsx @@ -6,39 +6,41 @@ import React from 'react'; import { useHistory, useParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import { Button } from 'coding-oa-uikit'; import PlusIcon from 'coding-oa-uikit/lib/icon/Plus'; // 项目内 import repoLogo from '@src/images/repo.svg'; -import { t } from '@src/i18n/i18next'; import { getReposRouter } from '@src/utils/getRoutePath'; import s from './style.scss'; const Welcome = () => { const history = useHistory(); - const { org_sid: orgSid, team_name: teamName }: any = useParams(); + const { t } = useTranslation(); + const { orgSid, teamName }: any = useParams(); return ( -
-
-

{t('欢迎使用代码库登记')}

-

- {t('登记仓库以便进行代码分析,支持')} - GIT、SVN - {t('代码库。支持可配置认证、选择成员等。')} -

-
- {t('代码库登记')} -
- -
-
+
+
+

{t('欢迎使用代码库登记')}

+

+ {t('登记仓库以便进行代码分析,支持')} + GIT、SVN + {t('代码库。支持可配置认证、选择成员等。')} +

+
+ {t('代码库登记')} +
+ +
+
); }; export default Welcome; diff --git a/web/packages/tca-analysis/src/modules/welcome/style.scss b/web/packages/tca-analysis/src/modules/welcome/style.scss index 86de5a21d..49454f899 100644 --- a/web/packages/tca-analysis/src/modules/welcome/style.scss +++ b/web/packages/tca-analysis/src/modules/welcome/style.scss @@ -1,5 +1,5 @@ -@import '@src/common/style/color.scss'; +@import '@tencent/micro-frontend-shared/style/color.scss'; .welcome-container { margin-top: 168px; diff --git a/web/packages/tca-analysis/src/plat/common/api.ts b/web/packages/tca-analysis/src/plat/common/api.ts new file mode 100644 index 000000000..af4a012d8 --- /dev/null +++ b/web/packages/tca-analysis/src/plat/common/api.ts @@ -0,0 +1,25 @@ +import { FetchManager, FetchAPIManager } from '@tencent/micro-frontend-shared/util/fetch'; + +// 项目内 +import { reLogin } from '@src/utils'; + +export const MAIN_SERVER_API = '/server/main/api/v3'; +export const ANALYSIS_SERVER_API = '/server/analysis/api/v3'; +export const ANALYSIS_SERVER_CODEDOG_API = '/api/codedog/analysis/v3/'; +export const LOGIN_SERVER_API = '/server/credential/api/v3'; + +/** 重新定义 fetch manager */ +const fetchManager = new FetchManager({ + headers: { + Authorization: `CodeDog ${localStorage.getItem('accessToken')}`, + }, + statusHandler: (response) => { + if (response.status === 401) { + reLogin('登录态已过期,重新登录...'); + } + }, +}); + +export const { get, post, put, patch, del, getFile } = fetchManager; + +export const fetchAPIManager = (url: string) => FetchAPIManager.getInstance(url, fetchManager); diff --git a/web/packages/tca-analysis/src/plat/common/routes.ts b/web/packages/tca-analysis/src/plat/common/routes.ts new file mode 100644 index 000000000..02e650acc --- /dev/null +++ b/web/packages/tca-analysis/src/plat/common/routes.ts @@ -0,0 +1,41 @@ +import { lazy } from 'react'; +import { RouteProps } from 'react-router-dom'; + +// 项目内 +import { BASE_ROUTE_PREFIX, TMPL_ROUTE_PREFIX } from '@src/constant'; + +const PTOverview = lazy(() => import('@src/modules/project-team/overview')); +const PTGroup = lazy(() => import('@src/modules/project-team/group')); +const AllRules = lazy(() => import('@src/modules/template/code-lint/all-rules')); +const PkgRules = lazy(() => import('@src/modules/template/code-lint/pkg-rules')); +const TemplateDetail = lazy(() => import('@src/modules/template/detail')); +const Template = lazy(() => import('@src/modules/template')); +// const PkgRules = lazy(() => import('@src/modules/template/code-lint/pkg-rules')); + + +const ROUTERS: RouteProps[] = [{ + path: `${BASE_ROUTE_PREFIX}/profile`, + exact: true, + component: PTOverview, +}, { + path: `${BASE_ROUTE_PREFIX}/group`, + exact: true, + component: PTGroup, +}, { + path: `${TMPL_ROUTE_PREFIX}/:id/check-profiles/:checkProfileId/pkg/:pkgId/add-rule`, + exact: true, + component: AllRules, +}, { + path: `${TMPL_ROUTE_PREFIX}/:id/check-profiles/:checkProfileId/pkg/:pkgId`, + exact: true, + component: PkgRules, +}, { + path: `${TMPL_ROUTE_PREFIX}/:id/:tabs?`, + component: TemplateDetail, +}, { + path: TMPL_ROUTE_PREFIX, + component: Template, +}]; + +export default ROUTERS; + diff --git a/web/packages/tca-analysis/src/plat/open/api.ts b/web/packages/tca-analysis/src/plat/open/api.ts new file mode 100644 index 000000000..5c2c83177 --- /dev/null +++ b/web/packages/tca-analysis/src/plat/open/api.ts @@ -0,0 +1 @@ +export * from '@src/plat/common/api'; diff --git a/web/packages/tca-analysis/src/plat/open/modules/schemes/compile-modal.tsx b/web/packages/tca-analysis/src/plat/open/modules/schemes/compile-modal.tsx new file mode 100644 index 000000000..4dbdf2906 --- /dev/null +++ b/web/packages/tca-analysis/src/plat/open/modules/schemes/compile-modal.tsx @@ -0,0 +1,59 @@ +// Copyright (c) 2021-2022 THL A29 Limited +// +// This source code file is made available under MIT License +// See LICENSE for details +// ============================================================================== + +/** + * 分析方案-代码检查-编译配置 + */ +import React from 'react'; +import { Modal, Form, Input } from 'coding-oa-uikit'; + +interface CompileConfigProps { + visible: boolean; + data: any; + onOk: (params: any) => void; + onClose: () => void; +} +const CompileConfig = ({ visible, data, onOk, onClose }: CompileConfigProps) => { + const [form] = Form.useForm(); + + const onFinish = (data: any) => { + onOk(data); + }; + + return ( + form.resetFields()} + onOk={() => { + form.validateFields().then(onFinish); + }} + > + + + + + + + + + + ); +}; + +export default CompileConfig; diff --git a/web/packages/tca-analysis/src/plat/open/routes.ts b/web/packages/tca-analysis/src/plat/open/routes.ts new file mode 100644 index 000000000..df19b4ccd --- /dev/null +++ b/web/packages/tca-analysis/src/plat/open/routes.ts @@ -0,0 +1,3 @@ +import ROUTERS from '@src/plat/common/routes'; + +export default ROUTERS; diff --git a/web/packages/tca-analysis/src/reducer/index.ts b/web/packages/tca-analysis/src/reducer/index.ts deleted file mode 100644 index e10cf7da6..000000000 --- a/web/packages/tca-analysis/src/reducer/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const initialState = {}; - -export interface ActionProps { - type: string; - payload: any; -} - -const reducer = (state = initialState, action: ActionProps) => { - switch (action.type) { - default: - return state; - } -}; -export default reducer; diff --git a/web/packages/tca-analysis/src/root.tsx b/web/packages/tca-analysis/src/root.tsx index c41101b6a..f69d84e03 100644 --- a/web/packages/tca-analysis/src/root.tsx +++ b/web/packages/tca-analysis/src/root.tsx @@ -1,55 +1,33 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React, { Suspense } from 'react'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { hot } from 'react-hot-loader'; - -import { - TMPL_ROUTE_PREFIX, - BASE_ROUTE_PREFIX, -} from '@src/common/constants'; -import Loading from '@src/components/loading'; +import Loading from '@tencent/micro-frontend-shared/component/loading'; +// 项目内 +import { BASE_ROUTE_PREFIX } from '@src/constant'; import Routers from '@src/routes'; -import Template from '@src/modules/template'; -import TemplateDetail from '@src/modules/template/detail'; -import PkgRules from '@src/modules/template/code-lint/pkg-rules'; -import AllRules from '@src/modules/template/code-lint/all-rules'; -import PTOverview from '@src/modules/project-team/overview'; -import PTGroup from '@src/modules/project-team/group'; +import routes from '@plat/routes'; +import { StoreProvider } from './context/store'; const Root = () => ( - - - - - - - - - - - {/* */} - - - + }> + + + {routes.map(item => ( + + ))} + + + + + + ); export default hot(module)(Root); diff --git a/web/packages/tca-analysis/src/routes/index.tsx b/web/packages/tca-analysis/src/routes/index.tsx index 4e510cb47..5d39b1c3c 100644 --- a/web/packages/tca-analysis/src/routes/index.tsx +++ b/web/packages/tca-analysis/src/routes/index.tsx @@ -9,7 +9,7 @@ import React, { useEffect, useState } from 'react'; import { Route, Switch, useParams, useHistory } from 'react-router-dom'; import { toNumber, isEmpty, get, find } from 'lodash'; -import { useStateStore, useDispatchStore } from '@src/context/store'; +import { useDispatchStore } from '@src/context/store'; import { SET_CUR_REPO, SET_PROJECT_MEMBER, @@ -21,7 +21,7 @@ import { SCHEMES_ROUTE_PREFIX, BASE_ROUTE_PREFIX, REPOS_ROUTE_PREFIX, -} from '@src/common/constants'; +} from '@src/constant'; // import { getBaseRouter } from '@src/utils/getRoutePath'; import { getRepos, getProjectTeamMembers } from '@src/services/common'; @@ -60,9 +60,10 @@ const PATH_NAME = ['/repos/create', '/template']; const Routers = () => { const history = useHistory(); - const { org_sid: orgSid, team_name: teamName }: any = useParams(); + const { orgSid, teamName }: any = useParams(); let { repoId }: any = useParams(); - const { repos } = useStateStore(); + const [repos, setRepos] = useState([]); + const dispatch = useDispatchStore(); const [loading, setLoading] = useState(true); const [isWelcome, setIsWelcome] = useState(PATH_NAME.every((path: any) => !window.location.pathname.match(path))); @@ -94,41 +95,26 @@ const Routers = () => { payload: true, }); const list = (await getRepoList()) || []; + if (!isEmpty(list)) { + setRepos(list); // 将获取的代码库列表存入SET_REPOS dispatch({ - type: 'SET_REPOS', + type: SET_REPOS, payload: list, }); } - setLoading(false); dispatch({ type: SET_REPOS_LOADING, payload: false, }); - + setLoading(false); // 成员设置 const members = await getProjectTeamMembers(orgSid, teamName); dispatch({ type: SET_PROJECT_MEMBER, payload: members, }); - - // 如果没有curRepo,则获取链接中的代码库或列表中第一个代码库 - // if (isEmpty(curRepo)) { - // const repo = repoId ? find(list, { id: repoId }) : list[0]; - - // // 存在repo,将其存入context - // if (!isEmpty(repo)) { - // dispatch({ - // type: SET_CUR_REPO, - // payload: repo, - // }); - // } else { - // // history.replace(`${getBaseRouter(orgSid, teamName)}/repos`); - // } - // } - // 由于切换项目时,curRepo存在,因此不用上述内容,切换项目重新set repo const repo = repoId ? find(list, { id: repoId }) : list[0]; // 存在repo,将其存入context diff --git a/web/packages/tca-analysis/src/services/common.ts b/web/packages/tca-analysis/src/services/common.ts index a3f8f0671..e76ea10bd 100644 --- a/web/packages/tca-analysis/src/services/common.ts +++ b/web/packages/tca-analysis/src/services/common.ts @@ -15,17 +15,17 @@ export const ANALYSIS_SERVER_API = '/server/analysis/api/v3'; export const ANALYSIS_SERVER_CODEDOG_API = '/api/codedog/analysis/v3/'; export const LOGIN_SERVER_API = '/server/credential/api/v3'; -export const getBaseURL = (org_sid: string, team_name: string) => `/orgs/${org_sid}/teams/${team_name}`; +export const getBaseURL = (orgSid: string, teamName: string) => `/orgs/${orgSid}/teams/${teamName}`; -export const getMainBaseURL = (org_sid: string, team_name: string) => `${MAIN_SERVER_API}${getBaseURL(org_sid, team_name)}`; +export const getMainBaseURL = (orgSid: string, teamName: string) => `${MAIN_SERVER_API}${getBaseURL(orgSid, teamName)}`; -export const getAnalysisBaseURL = (org_sid: string, team_name: string) => `${ANALYSIS_SERVER_API}${getBaseURL(org_sid, team_name)}`; +export const getAnalysisBaseURL = (orgSid: string, teamName: string) => `${ANALYSIS_SERVER_API}${getBaseURL(orgSid, teamName)}`; /** * 获取代码库列表 * @param query */ -export const getRepos = (org_sid: string, team_name: string, query: any) => get(`${MAIN_SERVER_API}/orgs/${org_sid}/teams/${team_name}/repos/`, { ...query, scope: 'all' }); +export const getRepos = (orgSid: string, teamName: string, query: any) => get(`${MAIN_SERVER_API}/orgs/${orgSid}/teams/${teamName}/repos/`, { ...query, scope: 'all' }); /** * 根据用户UID获取用户信息 @@ -91,4 +91,4 @@ export const getOrgMembers = (orgSid: string) => get(`${MAIN_SERVER_API}/orgs/${ * @param teamName * @param params */ - export const disableProject = (orgSid: string, teamName: string, params: any) => put(`${getMainBaseURL(orgSid, teamName)}/status/`, params); +export const disableProject = (orgSid: string, teamName: string, params: any) => put(`${getMainBaseURL(orgSid, teamName)}/status/`, params); diff --git a/web/packages/tca-analysis/src/services/index.ts b/web/packages/tca-analysis/src/services/index.ts index 956bcdc76..12d45cca3 100644 --- a/web/packages/tca-analysis/src/services/index.ts +++ b/web/packages/tca-analysis/src/services/index.ts @@ -8,15 +8,14 @@ import qs from 'qs'; import { values, isEmpty } from 'lodash'; import { message } from 'coding-oa-uikit'; -import fetch from '../utils/fetch'; -import { t } from '@src/i18n/i18next'; +import fetch from '@src/utils/fetch'; import { reLogin } from '../utils'; export const ERROR_CODE = -1; function jsonInterceptor(res: any) { if (res.status === 401) { - reLogin(t('登录失效,请重新登录...')); + reLogin('登录失效,请重新登录...'); return Promise.reject(); } @@ -104,17 +103,14 @@ export function postFile(url: string, data?: any) { }, body: JSON.stringify(data), }) - .then(res => { + .then((res) => { if (res.status === 200) { - return Promise.resolve(res) - } - else if (res.status === 401) { - reLogin(t('登录失效,请重新登录...')); + return Promise.resolve(res); + } if (res.status === 401) { + reLogin('登录失效,请重新登录...'); return Promise.reject(); } - else { - return Promise.reject(res.json().then(errorInterceptor)) - } + return Promise.reject(res.json().then(errorInterceptor)); }) .catch((err: any) => Promise.reject(err)); } diff --git a/web/packages/tca-analysis/src/services/projects.ts b/web/packages/tca-analysis/src/services/projects.ts index 29628fdc7..36deaaebb 100644 --- a/web/packages/tca-analysis/src/services/projects.ts +++ b/web/packages/tca-analysis/src/services/projects.ts @@ -12,119 +12,119 @@ import { get, post, put, del, getFile, postFile } from './index'; import { MAIN_SERVER, MAIN_SERVER_API, ANALYSIS_SERVER_API, getMainBaseURL, getAnalysisBaseURL } from './common'; -const getProjectBaseURL = (org_sid: string, team_name: string, repoId: string | number, projectId: number) => `${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}`; +const getProjectBaseURL = (orgSid: string, teamName: string, repoId: string | number, projectId: number) => `${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}`; /** * 获取分支项目 * @param repoId - 代码库ID * @param query - 查询参数 */ -export const getProjects = (org_sid: string, team_name: string, repoId: string | number, query: any) => get(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/`, query); +export const getProjects = (orgSid: string, teamName: string, repoId: string | number, query: any) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/`, query); /** * 新建分支项目 * @param repoId - 代码库ID * @param data */ -export const createProject = (org_sid: string, team_name: string, repoId: string | number, data: any) => post(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/`, data); +export const createProject = (orgSid: string, teamName: string, repoId: string | number, data: any) => post(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/`, data); /** * 启动分析 - * @param org_sid - * @param team_name - * @param repoId - * @param projectId - * @param data + * @param orgSid + * @param teamName + * @param repoId + * @param projectId + * @param data */ -export const createJob = (org_sid: string, team_name: string, repoId: string | number, projectId: string | number, data: any) => post(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/scans/`, data); +export const createJob = (orgSid: string, teamName: string, repoId: string | number, projectId: string | number, data: any) => post(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/scans/`, data); /** * 获取分支项目信息 * @param repoId - 代码库ID * @param projectId - 项目ID */ -export const getProjectDetail = (org_sid: string, team_name: string, repoId: string | number, projectId: string | number) => get(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/`); +export const getProjectDetail = (orgSid: string, teamName: string, repoId: string | number, projectId: string | number) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/`); /** * 获取分支项目信息 * @param repoId - 代码库ID * @param projectId - 项目ID */ - export const delProject = (org_sid: string, team_name: string, repoId: string | number, projectId: string | number) => del(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/`); +export const delProject = (orgSid: string, teamName: string, repoId: string | number, projectId: string | number) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/`); /** * 获取指定代码库下与 CodeDog 关联的分支 * @param repoId - 代码库ID */ -export const getBranchs = (org_sid: string, team_name: string, repoId: number) => get(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/branchnames/`, { offset: 0, limit: 500 }); +export const getBranchs = (orgSid: string, teamName: string, repoId: number) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/branchnames/`, { offset: 0, limit: 500 }); /** * 获取指定分支关联的分析方案 * @param repoId - 代码库ID * @param branch - 分支名称 */ -export const getSchemesByBranch = (org_sid: string, team_name: string, repoId: number, branch: string) => get(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/branch/projects/`, { branch, scheme_status: 1 }); +export const getSchemesByBranch = (orgSid: string, teamName: string, repoId: number, branch: string) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/branch/projects/`, { branch, scheme_status: 1 }); /** * 开启第一次代码分析 * @param repoId * @param data */ -export const initRepos = (org_sid: string, team_name: string, repoId: number, data: any) => post(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/init/`, data); +export const initRepos = (orgSid: string, teamName: string, repoId: number, data: any) => post(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/init/`, data); /** * 本地分析 - 下载配置文件 - * @param org_sid - * @param team_name + * @param orgSid + * @param teamName * @param repoId * @param projectId * @param data: {source_dir: 本地代码绝对路径, total_scan: 是否全量分析} */ -export const downloadIniFile = (org_sid: string, team_name: string, repoId: number, projectId: number, data: any) => { +export const downloadIniFile = (orgSid: string, teamName: string, repoId: number, projectId: number, data: any) => { const env = `${window.location.origin}${MAIN_SERVER}`; - return postFile(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/scans/puppyini/`, { codedog_env: env, ...data }) -} + return postFile(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/scans/puppyini/`, { codedog_env: env, ...data }); +}; // ============================================ 分支概览 ============================================ /** * 获取代码检查最近问题信息 * @param projectId 分支项目ID */ -export const getLatestLintScans = (org_sid: string, team_name: string, repoId: number, projectId: number) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/lintscans/latest/`); +export const getLatestLintScans = (orgSid: string, teamName: string, repoId: number, projectId: number) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/lintscans/latest/`); /** * 获取代码检查历史详情数据 * @param projectId 分支项目ID * @param query 查询参数 */ -export const getLintScans = (org_sid: string, team_name: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/lintscans/`, query); +export const getLintScans = (orgSid: string, teamName: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/lintscans/`, query); /** * 获取圈复杂度历史详情数据 * @param projectId 分支项目ID * @param query 查询参数 */ -export const getCCScans = (org_sid: string, team_name: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/cycscans/`, query); +export const getCCScans = (orgSid: string, teamName: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/cycscans/`, query); /** * 获取重复代码历史详情数据 * @param projectId 分支项目ID * @param query 查询参数 */ -export const getDupScans = (org_sid: string, team_name: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/dupscans/`, query); +export const getDupScans = (orgSid: string, teamName: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/dupscans/`, query); /** * 获取代码统计历史详情数据 * @param projectId 分支项目ID * @param query 查询参数 */ -export const getClocScans = (org_sid: string, team_name: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/clocscans/`, query); +export const getClocScans = (orgSid: string, teamName: string, repoId: number, projectId: number, query?: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/clocscans/`, query); /** * 获取与我相关的数据 * @param projectId 分支项目ID */ -export const getMineOverview = (org_sid: string, team_name: string, repoId: number, projectId: number) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/overview/mine/`); +export const getMineOverview = (orgSid: string, teamName: string, repoId: number, projectId: number) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/overview/mine/`); // ============================================ 问题列表 ============================================ @@ -133,35 +133,35 @@ export const getMineOverview = (org_sid: string, team_name: string, repoId: numb * @param projectId * @param query */ -export const getIssues = (org_sid: string, team_name: string, repoId: number, projectId: number, query: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/`, query); +export const getIssues = (orgSid: string, teamName: string, repoId: number, projectId: number, query: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/`, query); /** * 问题列表 - 批量处理问题 * @param projectId * @param data */ -export const handleIssues = (org_sid: string, team_name: string, repoId: number, projectId: number, data: any) => put(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/resolution/`, data); +export const handleIssues = (orgSid: string, teamName: string, repoId: number, projectId: number, data: any) => put(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/resolution/`, data); /** * 问题列表 - 获取问题详情 * @param projectId * @param issueId */ -export const getIssueDetail = (org_sid: string, team_name: string, repoId: number, projectId: number, issueId: number) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/`); +export const getIssueDetail = (orgSid: string, teamName: string, repoId: number, projectId: number, issueId: number) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/`); /** * 问题列表 - 文件代码 * @param projectId * @param data */ -export const getCodeFile = (org_sid: string, team_name: string, repoId: number, projectId: number, data: any) => get(`${getMainBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codefile/`, data); +export const getCodeFile = (orgSid: string, teamName: string, repoId: number, projectId: number, data: any) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codefile/`, data); /** * 问题列表 - 获取指定 issue 操作记录 * @param projectId * @param issueId */ -export const getIssueDetailComments = (org_sid: string, team_name: string, repoId: number, projectId: number, issueId: number) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/comments/`); +export const getIssueDetailComments = (orgSid: string, teamName: string, repoId: number, projectId: number, issueId: number) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/comments/`); /** * 问题列表 - 更新指定 issue 的严重级别 @@ -169,7 +169,7 @@ export const getIssueDetailComments = (org_sid: string, team_name: string, repoI * @param issueId * @param severity - 严重级别 */ -export const updateIssueSeverity = (org_sid: string, team_name: string, repoId: number, projectId: number, issueId: number, severity: number) => put(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/severity/`, { +export const updateIssueSeverity = (orgSid: string, teamName: string, repoId: number, projectId: number, issueId: number, severity: number) => put(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/severity/`, { severity, }); @@ -179,19 +179,19 @@ export const updateIssueSeverity = (org_sid: string, team_name: string, repoId: * @param issueId * @param author - 责任人 */ -export const updateIssueAuthor = (org_sid: string, team_name: string, repoId: number, projectId: number, issueId: number, author: string) => put(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/author/`, { +export const updateIssueAuthor = (orgSid: string, teamName: string, repoId: number, projectId: number, issueId: number, author: string) => put(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/author/`, { author, }); /** * 问题列表 - 批量更新问题责任人 - * @param org_sid - * @param team_name + * @param orgSid + * @param teamName * @param repoId * @param projectId * @param data */ -export const updateIssuesAuthor = (org_sid: string, team_name: string, repoId: number, projectId: number, data: any) => put(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/author/`, data); +export const updateIssuesAuthor = (orgSid: string, teamName: string, repoId: number, projectId: number, data: any) => put(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/author/`, data); /** * 问题列表 - 忽略问题 @@ -200,14 +200,14 @@ export const updateIssuesAuthor = (org_sid: string, team_name: string, repoId: n * @param data */ export const resoluteIssue = ( - org_sid: string, - team_name: string, + orgSid: string, + teamName: string, repoId: number, projectId: number, issueId: number, data: any, ) => put( - `${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/resolution/`, + `${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/codelint/issues/${issueId}/resolution/`, data, ); @@ -365,39 +365,39 @@ export const getDupFileIssueComments = (orgSid: string, teamName: string, repoId * @param projectId - 分支项目ID * @param query - 查询参数 */ -export const getScans = (org_sid: string, team_name: string, repoId: number, projectId: number, query: any) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/scans/`, query); +export const getScans = (orgSid: string, teamName: string, repoId: number, projectId: number, query: any) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/scans/`, query); /** * 获取分析历史结果 - * @param org_sid - * @param team_name - * @param repoId - * @param projectId - * @param scanId + * @param orgSid + * @param teamName + * @param repoId + * @param projectId + * @param scanId */ -export const getScansResult = (org_sid: string, team_name: string, repoId: number, projectId: number, scanId: number) => get(`${getAnalysisBaseURL(org_sid, team_name)}/repos/${repoId}/projects/${projectId}/scans/${scanId}/`); +export const getScansResult = (orgSid: string, teamName: string, repoId: number, projectId: number, scanId: number) => get(`${getAnalysisBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}/scans/${scanId}/`); /** * 分析历史 - 获取分析历史详情 - * @param org_sid - * @param team_name + * @param orgSid + * @param teamName * @param repoId * @param projectId * @param jobId */ -export const getScanDetail = (org_sid: string, team_name: string, repoId: number, projectId: number, jobId: number) => get(`${getProjectBaseURL(org_sid, team_name, repoId, projectId)}/jobs/${jobId}/`); +export const getScanDetail = (orgSid: string, teamName: string, repoId: number, projectId: number, jobId: number) => get(`${getProjectBaseURL(orgSid, teamName, repoId, projectId)}/jobs/${jobId}/`); /** * 分析历史 - 获取分析历史详情 - 子任务详细信息 - * @param org_sid - * @param team_name + * @param orgSid + * @param teamName * @param repoId * @param projectId * @param jobId * @param taskId */ -export const getTaskDetail = (org_sid: string, team_name: string, repoId: number, projectId: number, jobId: number, taskId: number) => get(`${getProjectBaseURL(org_sid, team_name, repoId, projectId)}/jobs/${jobId}/tasks/${taskId}/`); +export const getTaskDetail = (orgSid: string, teamName: string, repoId: number, projectId: number, jobId: number, taskId: number) => get(`${getProjectBaseURL(orgSid, teamName, repoId, projectId)}/jobs/${jobId}/tasks/${taskId}/`); /** * 分析历史 - 取消分析 diff --git a/web/packages/tca-analysis/src/services/repos.ts b/web/packages/tca-analysis/src/services/repos.ts index 0794d83b7..3e1a0287d 100644 --- a/web/packages/tca-analysis/src/services/repos.ts +++ b/web/packages/tca-analysis/src/services/repos.ts @@ -23,10 +23,10 @@ export const getScmAccounts = () => get(`${MAIN_SERVER_API}/authen/scmaccounts/` */ export const getSSHInfo = () => get(`${MAIN_SERVER_API}/authen/scmsshinfos/`, { limit: 200 }); - /** +/** * 查询所有OAuth授权状况 */ - export const getOAuthInfo = () => get(`${MAIN_SERVER_API}/authen/scmauthinfos/`); +export const getOAuthInfo = () => get(`${MAIN_SERVER_API}/authen/scmauthinfos/`); /** * 查询OAuth授权配置状况 @@ -38,7 +38,7 @@ export const getPlatformStatus = (param: any = null) => get(`${MAIN_SERVER_API}/ * 登记代码库 * @param data: { name: 代码库名称, scm_type: 代码库来源 git/svn, scm_url: 代码库地址 } */ -export const postRepo = (org_sid: string, name: string, data: any) => post(`${getMainBaseURL(org_sid, name)}/repos/`, data); +export const postRepo = (orgSid: string, name: string, data: any) => post(`${getMainBaseURL(orgSid, name)}/repos/`, data); /** * 认证方式 @@ -72,4 +72,4 @@ export const postRepoMembers = (orgSid: string, teamName: string, repoId: any, d * 删除代码库 * @param repoId: 代码库id */ - export const delRepo = (orgSid: string, teamName: string, repoId: any) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/`); +export const delRepo = (orgSid: string, teamName: string, repoId: any) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/`); diff --git a/web/packages/tca-analysis/src/services/schemes.ts b/web/packages/tca-analysis/src/services/schemes.ts index cc10ff2b8..5a87372c4 100644 --- a/web/packages/tca-analysis/src/services/schemes.ts +++ b/web/packages/tca-analysis/src/services/schemes.ts @@ -13,6 +13,16 @@ import { get, post, put, del } from './index'; import { MAIN_SERVER_API, getMainBaseURL } from './common'; +/** + * 分析方案前缀 + * @param orgSid + * @param teamName + * @param repoId + * @param schemeId + * @returns + */ +const getSchemePrefix = (orgSid: string, teamName: string, repoId: string | number, schemeId: string | number) => `${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/schemes/${schemeId}`; + /** * 获取分析方案列表 * @param orgSid 团队唯一标识 @@ -274,6 +284,17 @@ export const addRule = (orgSid: string, teamName: string, repoId: string | numbe */ export const getRuleDetail = (orgSid: string, teamName: string, repoId: string | number, schemeId: string | number, ruleId: number) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/schemes/${schemeId}/allrules/${ruleId}/`); +/** + * 代码检查 - 获取指定规则的详细信息 + * @param {*} toolName - 工具名称 + * @param {*} ruleRealName - 规则真实名称 + * @returns + */ +export const getRuleDetailByName = (orgSid: string, teamName: string, repoId: string | number, schemeId: string | number, toolName: string, ruleRealName: string) => get(`${getSchemePrefix(orgSid, teamName, repoId, schemeId)}/allrules/byname/`, { + checktool_name: toolName, + checkrule_real_name: ruleRealName, +}); + // ============================================ 分析方案 - 代码度量 ============================================ /** @@ -412,3 +433,9 @@ export const importScanDir = (orgSid: string, teamName: string, repoId: number, * @returns */ export const getBranchs = (orgSid: string, teamName: string, repoId: number, schemeId: number, query: any) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/schemes/${schemeId}/branchs/`, query); + +/** + * 获取工具列表 + * @param {*} query + */ +export const getCheckTools = (orgId: string, query: any) => get(`${MAIN_SERVER_API}/orgs/${orgId}/checktools/`, query); diff --git a/web/packages/tca-analysis/src/services/template.tsx b/web/packages/tca-analysis/src/services/template.tsx index 6bc18f16d..66e7697f8 100644 --- a/web/packages/tca-analysis/src/services/template.tsx +++ b/web/packages/tca-analysis/src/services/template.tsx @@ -13,238 +13,238 @@ import { get, post, put, del } from './index'; import { MAIN_SERVER_API } from './common'; -export const getTmplBaseURL = (org_sid: string) => `${MAIN_SERVER_API}/orgs/${org_sid}/schemes`; +export const getTmplBaseURL = (orgSid: string) => `${MAIN_SERVER_API}/orgs/${orgSid}/schemes`; /** * 获取模板列表 * @param query */ -export const getTmplList = (org_sid: string, query: any) => get(`${getTmplBaseURL(org_sid)}/`, query); +export const getTmplList = (orgSid: string, query: any) => get(`${getTmplBaseURL(orgSid)}/`, query); /** * 创建模板 * @param data */ -export const createTmpl = (org_sid: string, data: any) => post(`${getTmplBaseURL(org_sid)}/`, data); +export const createTmpl = (orgSid: string, data: any) => post(`${getTmplBaseURL(orgSid)}/`, data); /** * 查询模板基本信息 * @param id */ -export const getTmplInfo = (org_sid: string, id: number) => get(`${getTmplBaseURL(org_sid)}/${id}/`); +export const getTmplInfo = (orgSid: string, id: number) => get(`${getTmplBaseURL(orgSid)}/${id}/`); /** * 更新模板信息 * @param id * @param data */ -export const updateTmpl = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/`, data); +export const updateTmpl = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/`, data); /** * 获取模板代码检查信息 * @param id */ -export const getTmplLint = (org_sid: string, id: number) => get(`${getTmplBaseURL(org_sid)}/${id}/lintconf/`); +export const getTmplLint = (orgSid: string, id: number) => get(`${getTmplBaseURL(orgSid)}/${id}/lintconf/`); /** * 更新模板代码检查 * @param id * @param data */ -export const updateTmplLint = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/lintconf/`, data); +export const updateTmplLint = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/lintconf/`, data); /** * 获取分析方案代码检查-官方规则包列表 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param query 筛选项 * @returns */ -export const getCheckPackages = (org_sid: string, id: number, query: any) => get(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/`, query); +export const getCheckPackages = (orgSid: string, id: number, query: any) => get(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/`, query); /** * 获取全部官方规则包列表 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id */ -export const getAllCheckPackages = (org_sid: string, id: number) => get(`${getTmplBaseURL(org_sid)}/${id}/allcheckpackages/`); +export const getAllCheckPackages = (orgSid: string, id: number) => get(`${getTmplBaseURL(orgSid)}/${id}/allcheckpackages/`); /** * 给规则配置添加规则包 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data 参数 */ -export const addCheckPackages = (org_sid: string, id: number, data: any) => post(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/`, { +export const addCheckPackages = (orgSid: string, id: number, data: any) => post(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/`, { checkpackages: data, }); /** * 给规则配置移除规则包 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param pkgId 规则包ID */ -export const delCheckPackage = (org_sid: string, id: number, pkgId: number) => del(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/${pkgId}/`); +export const delCheckPackage = (orgSid: string, id: number, pkgId: number) => del(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/${pkgId}/`); /** * 获取规则包详情 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param pkgId 规则包ID */ -export const getCheckPackagesDetail = (org_sid: string, id: number, pkgId: number) => get(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/${pkgId}/`); +export const getCheckPackagesDetail = (orgSid: string, id: number, pkgId: number) => get(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/${pkgId}/`); /** * 获取规则包规则列表 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param pkgId 规则包ID * @param query 筛选项 */ -export const getPackagesRule = (org_sid: string, id: number, pkgId: number, query: any) => get(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/${pkgId}/rules/`, query); +export const getPackagesRule = (orgSid: string, id: number, pkgId: number, query: any) => get(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/${pkgId}/rules/`, query); /** * 获取规则包下规则的过滤信息 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param pkgId 规则包ID */ -export const getRulesFilter = (org_sid: string, id: number, pkgId: number) => get(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/checkpackages/${pkgId}/rules/filter/`); +export const getRulesFilter = (orgSid: string, id: number, pkgId: number) => get(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/checkpackages/${pkgId}/rules/filter/`); /** * 代码检查-规则配置-修改规则状态 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data 参数 */ -export const modifyRuleState = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/rules/modifystate/`, data); +export const modifyRuleState = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/rules/modifystate/`, data); /** * 代码检查-规则配置-修改规则严重级别 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data 参数 */ -export const modifyRuleSeverity = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/rules/modifyseverity/`, data); +export const modifyRuleSeverity = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/rules/modifyseverity/`, data); /** * 代码检查-规则配置-修改规则信息 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data 参数 */ -export const modifyRule = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/rules/modify/`, data); +export const modifyRule = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/rules/modify/`, data); /** * 代码检查-规则配置-移除规则 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data */ -export const delRule = (org_sid: string, id: number, data: any) => del(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/rules/delete/`, data); +export const delRule = (orgSid: string, id: number, data: any) => del(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/rules/delete/`, data); /** * 获取全部规则列表 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param query 筛选项 */ -export const getAllRules = (org_sid: string, id: number, query: any) => get(`${getTmplBaseURL(org_sid)}/${id}/allrules/`, query); +export const getAllRules = (orgSid: string, id: number, query: any) => get(`${getTmplBaseURL(orgSid)}/${id}/allrules/`, query); /** * 代码检查-规则配置-批量添加规则 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data 参数 */ -export const addRule = (org_sid: string, id: number, data: any) => post(`${getTmplBaseURL(org_sid)}/${id}/checkprofile/rules/create/`, data); +export const addRule = (orgSid: string, id: number, data: any) => post(`${getTmplBaseURL(orgSid)}/${id}/checkprofile/rules/create/`, data); /** * 代码检查 - 规则配置 - 规则详情 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param ruleId */ -export const getRuleDetail = (org_sid: string, id: number, ruleId: number) => get(`${getTmplBaseURL(org_sid)}/${id}/allrules/${ruleId}/`); +export const getRuleDetail = (orgSid: string, id: number, ruleId: number) => get(`${getTmplBaseURL(orgSid)}/${id}/allrules/${ruleId}/`); /** * 获取代码度量数据 * @param id */ -export const getTmplMetrics = (org_sid: string, id: number) => get(`${getTmplBaseURL(org_sid)}/${id}/metricconf/`); +export const getTmplMetrics = (orgSid: string, id: number) => get(`${getTmplBaseURL(orgSid)}/${id}/metricconf/`); /** * 更新代码度量数据 * @param id * @param data */ -export const updateTmplMetrics = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/metricconf/`, data); +export const updateTmplMetrics = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/metricconf/`, data); /** * 获取过滤路径 * @param id * @param query */ -export const getTmplScanDir = (org_sid: string, id: number, query: any) => get(`${getTmplBaseURL(org_sid)}/${id}/scandirs/`, query); +export const getTmplScanDir = (orgSid: string, id: number, query: any) => get(`${getTmplBaseURL(orgSid)}/${id}/scandirs/`, query); /** * 添加过滤路径 * @param id * @param data */ -export const addTmplScanDir = (org_sid: string, id: number, data: any) => post(`${getTmplBaseURL(org_sid)}/${id}/scandirs/`, data); +export const addTmplScanDir = (orgSid: string, id: number, data: any) => post(`${getTmplBaseURL(orgSid)}/${id}/scandirs/`, data); /** * 编辑过滤路径 * @param id * @param data */ -export const updateTmplScanDir = (org_sid: string, id: number, scanDirId: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/scandirs/${scanDirId}/`, data); +export const updateTmplScanDir = (orgSid: string, id: number, scanDirId: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/scandirs/${scanDirId}/`, data); /** * 删除过滤路径 * @param id * @param scanDirId */ -export const delTmplScanDir = (org_sid: string, id: number, scanDirId: number) => del(`${getTmplBaseURL(org_sid)}/${id}/scandirs/${scanDirId}/`); +export const delTmplScanDir = (orgSid: string, id: number, scanDirId: number) => del(`${getTmplBaseURL(orgSid)}/${id}/scandirs/${scanDirId}/`); /** * 批量删除过滤路径 * @param id */ -export const delAllTmplScanDir = (org_sid: string, id: number) => del(`${getTmplBaseURL(org_sid)}/${id}/scandirs/clear/`); +export const delAllTmplScanDir = (orgSid: string, id: number) => del(`${getTmplBaseURL(orgSid)}/${id}/scandirs/clear/`); /** * 批量导入过滤路径 * @param id * @param data */ -export const importTmplScanDir = (org_sid: string, id: number, data: any) => post(`${getTmplBaseURL(org_sid)}/${id}/scandirs/bulkcreate/`, data); +export const importTmplScanDir = (orgSid: string, id: number, data: any) => post(`${getTmplBaseURL(orgSid)}/${id}/scandirs/bulkcreate/`, data); /** * 获取指定模板生成的分析方案 * @param id */ -export const getSchemeList = (org_sid: string, id: number, query: any) => get(`${getTmplBaseURL(org_sid)}/${id}/childrens/`, query); +export const getSchemeList = (orgSid: string, id: number, query: any) => get(`${getTmplBaseURL(orgSid)}/${id}/childrens/`, query); /** * 模板同步 - * @param org_sid 团队唯一标识 + * @param orgSid 团队唯一标识 * @param id * @param data */ -export const syncScheme = (org_sid: string, id: number, data: any) => post(`${getTmplBaseURL(org_sid)}/${id}/push/`, data); +export const syncScheme = (orgSid: string, id: number, data: any) => post(`${getTmplBaseURL(orgSid)}/${id}/push/`, data); /** * 获取模板权限 * @param id */ -export const getPermConf = (org_sid: string, id: number) => get(`${getTmplBaseURL(org_sid)}/${id}/permconf/`); +export const getPermConf = (orgSid: string, id: number) => get(`${getTmplBaseURL(orgSid)}/${id}/permconf/`); /** * 修改模板权限 * @param id * @param data */ -export const updatePermConf = (org_sid: string, id: number, data: any) => put(`${getTmplBaseURL(org_sid)}/${id}/permconf/`, data); +export const updatePermConf = (orgSid: string, id: number, data: any) => put(`${getTmplBaseURL(orgSid)}/${id}/permconf/`, data); diff --git a/web/packages/tca-analysis/src/store/common.ts b/web/packages/tca-analysis/src/store/common.ts new file mode 100644 index 000000000..3f7b8e699 --- /dev/null +++ b/web/packages/tca-analysis/src/store/common.ts @@ -0,0 +1,4 @@ +export interface DefaultAction { + type: string + payload: any +} diff --git a/web/packages/tca-analysis/src/store/index.ts b/web/packages/tca-analysis/src/store/index.ts new file mode 100644 index 000000000..3ace726fc --- /dev/null +++ b/web/packages/tca-analysis/src/store/index.ts @@ -0,0 +1,4 @@ +import teamStore from './team'; +import repoStore from './repo'; + +export default [teamStore, repoStore]; diff --git a/web/packages/tca-analysis/src/store/repo.ts b/web/packages/tca-analysis/src/store/repo.ts new file mode 100644 index 000000000..76fbfa9c1 --- /dev/null +++ b/web/packages/tca-analysis/src/store/repo.ts @@ -0,0 +1,45 @@ +import { Store, Reducer } from '@tencent/micro-frontend-shared/hook-store/types'; +import { DefaultAction } from './common'; + +/** 命名空间 */ +export const NAMESPACE = 'REPO'; + +export const SET_CUR_REPO = 'SET_CUR_REPO'; +export const SET_CUR_REPO_MEMBER = 'SET_CUR_REPO_MEMBER'; + +export interface RepoState { + /** 代码库详情 */ + repoInfo: any; + /** 代码库管理成员信息 */ + admins: any[]; + /** 代码库普通成员信息 */ + users: any[]; +} + +const initialState: RepoState = { + repoInfo: {}, + admins: [], + users: [], +}; + +const reducer: Reducer = (state, action) => { + switch (action.type) { + case SET_CUR_REPO: + return { ...state, repoInfo: action.payload }; + case SET_CUR_REPO_MEMBER: { + const { admins = [], users = [] } = action.payload; + return { ...state, admins, users }; + } + default: + return state; + } +}; + +const store: Store = { + name: NAMESPACE, + initialState, + reducer, +}; + +export default store; + diff --git a/web/packages/tca-analysis/src/store/team.ts b/web/packages/tca-analysis/src/store/team.ts new file mode 100644 index 000000000..ed516565e --- /dev/null +++ b/web/packages/tca-analysis/src/store/team.ts @@ -0,0 +1,51 @@ +import { Store, Reducer } from '@tencent/micro-frontend-shared/hook-store/types'; +import { DefaultAction } from './common'; + +/** 命名空间 */ +export const NAMESPACE = 'TEAM'; + +export const SET_PROJECT_MEMBER = 'SET_PROJECT_MEMBER'; +export const SET_REPOS = 'SET_REPOS'; +export const SET_REPOS_LOADING = 'SET_REPOS_LOADING'; + +export interface TeamState { + /** 项目组代码库列表 */ + repos: any[]; + /** 代码库列表加载状态 */ + reposLoading: boolean; + /** 项目组管理员成员信息 */ + admins: any[]; + /** 项目组普通员成员信息 */ + users: any[] +} + +const initialState: TeamState = { + repos: [], + reposLoading: false, + admins: [], + users: [], +}; + +const reducer: Reducer = (state, action) => { + switch (action.type) { + case SET_PROJECT_MEMBER: { + const { admins = [], users = [] } = action.payload; + return { ...state, admins, users }; + } + case SET_REPOS: + return { ...state, repos: action.payload }; + case SET_REPOS_LOADING: + return { ...state, reposLoading: action.payload }; + default: + return state; + } +}; + +const store: Store = { + name: NAMESPACE, + initialState, + reducer, +}; + +export default store; + diff --git a/web/packages/tca-analysis/src/store/types.ts b/web/packages/tca-analysis/src/store/types.ts new file mode 100644 index 000000000..6267fcfef --- /dev/null +++ b/web/packages/tca-analysis/src/store/types.ts @@ -0,0 +1,6 @@ +import { RepoState } from './repo'; +import { TeamState } from './team'; +import { DefaultAction } from './common'; + +export type State = TeamState | RepoState; +export type Action = DefaultAction; diff --git a/web/packages/tca-analysis/src/utils/fetch.ts b/web/packages/tca-analysis/src/utils/fetch.ts index fd4dacaff..61861583d 100644 --- a/web/packages/tca-analysis/src/utils/fetch.ts +++ b/web/packages/tca-analysis/src/utils/fetch.ts @@ -27,8 +27,6 @@ export default function fetch(url: string, options: any, absolutePath = false) { const contentType = get(options, 'headers.Content-Type'); let headers: any = { - // 'API-TYPE': 'coding', - // 'CODING-PROJECT': get(window.reduxStore.getState(), 'APP.currentProject.id') }; const tk = localStorage.getItem('accessToken'); diff --git a/web/packages/tca-analysis/src/utils/getRoutePath.ts b/web/packages/tca-analysis/src/utils/getRoutePath.ts index c053b596a..5c56f41da 100644 --- a/web/packages/tca-analysis/src/utils/getRoutePath.ts +++ b/web/packages/tca-analysis/src/utils/getRoutePath.ts @@ -7,30 +7,30 @@ /** * 获取项目列表路由地址 - * @param org_sid + * @param orgSid */ - export const getProjectListRouter = (org_sid: string) => `/t/${org_sid}/projects`; +export const getProjectListRouter = (orgSid: string) => `/t/${orgSid}/projects`; - /** +/** * 获取项目概览路由地址 - * @param org_sid + * @param orgSid * @param name */ - export const getProjectOverviewRouter = (org_sid: string, name: string) => `/t/${org_sid}/p/${name}/profile`; +export const getProjectOverviewRouter = (orgSid: string, name: string) => `/t/${orgSid}/p/${name}/profile`; /** * 获取基础路由前缀 - * @param org_sid + * @param orgSid * @param name */ -export const getBaseRouter = (org_sid: string, name: string) => `/t/${org_sid}/p/${name}`; +export const getBaseRouter = (orgSid: string, name: string) => `/t/${orgSid}/p/${name}`; /** * 获取代码库路由前缀 - * @param org_sid + * @param orgSid * @param name */ -export const getReposRouter = (org_sid: string, name: string) => `/t/${org_sid}/p/${name}/repos`; +export const getReposRouter = (orgSid: string, name: string) => `/t/${orgSid}/p/${name}/repos`; /** * 获取分支项目路由前缀 @@ -38,7 +38,7 @@ export const getReposRouter = (org_sid: string, name: string) => `/t/${org_sid}/ * @param {string | number} repoId - 仓库ID * @param {string | number} [projectId] - 项目ID */ -export const getProjectRouter = (org_sid: string, name: string, repoId: string | number, projectId?: string | number) => `${getBaseRouter(org_sid, name)}/code-analysis/repos/${repoId}/projects${projectId ? `/${projectId}` : ''}`; +export const getProjectRouter = (orgSid: string, name: string, repoId: string | number, projectId?: string | number) => `${getBaseRouter(orgSid, name)}/code-analysis/repos/${repoId}/projects${projectId ? `/${projectId}` : ''}`; /** * 获取分析方案路由前缀 @@ -47,12 +47,21 @@ export const getProjectRouter = (org_sid: string, name: string, repoId: string | * @param {string | number} [schemeId] - 分析方案ID */ export const getSchemeRouter = ( - org_sid: string, + orgSid: string, name: string, repoId: string | number, schemeId?: string | number, -) => `${getBaseRouter(org_sid, name)}/code-analysis/repos/${repoId}/schemes${schemeId ? `/${schemeId}` : ''}`; +) => `${getBaseRouter(orgSid, name)}/code-analysis/repos/${repoId}/schemes${schemeId ? `/${schemeId}` : ''}`; export const getTmplRouter = (orgSid: string, teamName: string) => `${getBaseRouter(orgSid, teamName)}/template`; -export const getTeamMemberRouter = (org_sid: string) => `/t/${org_sid}/members`; +/** + * 工具管理路由 + * @param orgSid + * @param teamName + * @param tab + * @returns + */ +export const getToolsRouter = (orgSid: string, toolId: number, tab: string) => `/t/${orgSid}/tools/${toolId}/${tab}`; + +export const getTeamMemberRouter = (orgSid: string) => `/t/${orgSid}/members`; diff --git a/web/packages/tca-analysis/src/utils/hooks.ts b/web/packages/tca-analysis/src/utils/hooks.ts index cfdd19202..71932cea5 100644 --- a/web/packages/tca-analysis/src/utils/hooks.ts +++ b/web/packages/tca-analysis/src/utils/hooks.ts @@ -1,9 +1,3 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import { useLocation } from 'react-router-dom'; /** diff --git a/web/packages/tca-analysis/tsconfig.json b/web/packages/tca-analysis/tsconfig.json index 167e4b0f5..ad7e2f8d0 100644 --- a/web/packages/tca-analysis/tsconfig.json +++ b/web/packages/tca-analysis/tsconfig.json @@ -5,6 +5,7 @@ "baseUrl": ".", // baseUrl用于设置解析非相对模块名称的基本目录,相对模块不会受到baseUrl的影响 "paths": { // paths用于设置模块名到基于baseUrl的路径映射 "@src/*": ["src/*"], + "@plat/*": ["src/plat/open/*"] } }, "include": ["src", "global.d.ts"] diff --git a/web/packages/tca-analysis/webpack.config.ts b/web/packages/tca-analysis/webpack.config.ts new file mode 100644 index 000000000..63661a83d --- /dev/null +++ b/web/packages/tca-analysis/webpack.config.ts @@ -0,0 +1,14 @@ +import { webpackConfig } from '@tencent/micro-frontend-webpack/src/index'; +import { merge } from 'webpack-merge'; + +const { config } = webpackConfig({ + configWebpackOptions: { + match: '^/t/[^/]+/p/[^/]+/(code-analysis|repos|template|profile|group)', + }, +}); + +export default merge(config, { + devServer: { + + }, +}); diff --git a/web/packages/tca-document/.gitignore b/web/packages/tca-document/.gitignore deleted file mode 100644 index d46af7243..000000000 --- a/web/packages/tca-document/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -.temp -.cache diff --git a/web/packages/tca-document/.vuepress/config.ts b/web/packages/tca-document/.vuepress/config.ts deleted file mode 100644 index 8f7c6f178..000000000 --- a/web/packages/tca-document/.vuepress/config.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { defineUserConfig } from '@vuepress/cli' -import { defaultTheme } from '@vuepress/theme-default' -import { navbar, sidebar } from './configs' -const { searchPlugin } = require('@vuepress/plugin-search') - -const isProd = process.env.NODE_ENV === 'production' - - -export default defineUserConfig({ - base: process.env.BASE ? `/${process.env.BASE}/` : '/', - - head: [ - [ - 'link', - { - rel: 'icon', - type: 'image/png', - href: `/images/favicon.png`, - }, - ], - ['meta', { name: 'msapplication-TileColor', content: '#3eaf7c' }], - ['meta', { name: 'theme-color', content: '#3eaf7c' }], - ], - - plugins: [ - searchPlugin({ - // 配置项 - }), - ], - - markdown: { - toc: { - level: [2, 3, 4], - } - }, - - // site-level locales config - locales: { - '/': { - lang: 'zh-CN', - title: '腾讯云代码分析', - description: '用心关注每行代码迭代、助力传承卓越代码文化!', - }, - '/en': { - lang: 'en-US', - title: 'Tencent Code Analysis', - description: '用心关注每行代码迭代、助力传承卓越代码文化!', - }, - }, - - - theme: defaultTheme({ - logo: '/images/favicon.png', - - repo: 'https://github.com/Tencent/CodeAnalysis', - - docsDir: 'doc', - - // theme-level locales config - locales: { - /** - * English locale config - * - * As the default locale of @vuepress/theme-default is English, - * we don't need to set all of the locale fields - */ - '/en': { - // navbar - navbar: navbar.en, - selectLanguageName: 'English', - selectLanguageText: 'Languages', - selectLanguageAriaLabel: 'Languages', - - // sidebar - sidebar: sidebar.en, - sidebarDepth: 1, - - // page meta - editLinkText: 'Edit this page on GitHub', - - }, - - /** - * Chinese locale config - */ - '/': { - // navbar - navbar: navbar.zh, - selectLanguageName: '简体中文', - selectLanguageText: '选择语言', - selectLanguageAriaLabel: '选择语言', - - // sidebar - sidebar: sidebar.zh, - sidebarDepth: 1, - - // page meta - editLinkText: '在 GitHub 上编辑此页', - lastUpdatedText: '上次更新', - contributorsText: '贡献者', - - // custom containers - tip: '提示', - warning: '注意', - danger: '警告', - - // 404 page - notFound: [ - '这里什么都没有', - '我们怎么到这来了?', - '这是一个 404 页面', - '看起来我们进入了错误的链接', - ], - backToHome: '返回首页', - - // a11y - openInNewWindow: '在新窗口打开', - toggleDarkMode: '切换夜间模式', - toggleSidebar: '切换侧边栏', - - }, - }, - - themePlugins: { - // only enable git plugin in production mode - git: isProd, - // use shiki plugin in production mode instead - prismjs: !isProd, - }, - - }), -}) diff --git a/web/packages/tca-document/.vuepress/configs/index.ts b/web/packages/tca-document/.vuepress/configs/index.ts deleted file mode 100644 index d3d9ad199..000000000 --- a/web/packages/tca-document/.vuepress/configs/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as navbar from './navbar' -export * as sidebar from './sidebar' \ No newline at end of file diff --git a/web/packages/tca-document/.vuepress/configs/navbar/en.ts b/web/packages/tca-document/.vuepress/configs/navbar/en.ts deleted file mode 100644 index 1ddb3af9e..000000000 --- a/web/packages/tca-document/.vuepress/configs/navbar/en.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { NavbarConfig } from '@vuepress/theme-default' - -export const en: NavbarConfig = [ - { - text: '快速入门', - link: '/en/quickStarted/deploySever.md', - }, - { - text: '帮助文档', - link: '/en/guide/', - }, - { - text: 'API', - link: '/en/api/', - }, - { - text: '了解更多', - children: [ - { - text: '深入', - children: [ - '/en/advanced/任务分布式执行.md', - '/en/advanced/集成代码分析工具.md', - ], - }, - { - text: '文章', - children: [ - - ], - }, - ] - }, - { - text: '社区', - children: [ - '/en/community/contribute.md', - '/en/community/changelog.md', - '/en/community/joingroup.md', - { - text: '体验官方版本', - link: 'https://tca.tencent.com/', - } - ] - }, -] - diff --git a/web/packages/tca-document/.vuepress/configs/navbar/index.ts b/web/packages/tca-document/.vuepress/configs/navbar/index.ts deleted file mode 100644 index 520a20301..000000000 --- a/web/packages/tca-document/.vuepress/configs/navbar/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './zh' -export * from './en' diff --git a/web/packages/tca-document/.vuepress/configs/navbar/zh.ts b/web/packages/tca-document/.vuepress/configs/navbar/zh.ts deleted file mode 100644 index 5a5974b7f..000000000 --- a/web/packages/tca-document/.vuepress/configs/navbar/zh.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { NavbarConfig } from '@vuepress/theme-default' - -export const zh: NavbarConfig = [ - { - text: '快速入门', - link: '/zh/quickStarted/deploySever.md', - }, - { - text: '帮助文档', - link: '/zh/guide/', - }, - { - text: 'API', - link: '/zh/api/', - }, - { - text: '了解更多', - children: [ - { - text: '深入', - children: [ - '/zh/advanced/任务分布式执行.md', - '/zh/advanced/集成代码分析工具.md', - ], - }, - { - text: '文章', - children: [ - - ], - }, - ] - }, - { - text: '社区', - children: [ - '/zh/community/contribute.md', - '/zh/community/changelog.md', - '/zh/community/joingroup.md', - { - text: '体验官方版本', - link: 'https://tca.tencent.com/', - } - ] - }, -] diff --git a/web/packages/tca-document/.vuepress/configs/sidebar/en.ts b/web/packages/tca-document/.vuepress/configs/sidebar/en.ts deleted file mode 100644 index e21e4c30d..000000000 --- a/web/packages/tca-document/.vuepress/configs/sidebar/en.ts +++ /dev/null @@ -1,150 +0,0 @@ -import type { SidebarConfig } from '@vuepress/theme-default' - -export const en: SidebarConfig = { - '/en/guide/': [ - { - text: '介绍', - children: [ - '/en/guide/README.md', - '/en/guide/快速入门/快速启动一次代码分析.md' - ], - }, - { - text: '团队管理', - children: [ - '/en/guide/团队管理/团队管理.md', - '/en/guide/团队管理/成员权限.md', - '/en/guide/团队管理/节点管理.md', - ] - }, - { - text: '代码检查', - children: [ - '/en/guide/代码检查/分析结果查看.md', - ] - }, - { - text: '分析方案', - children: [ - '/en/guide/分析方案/基础属性配置.md', - '/en/guide/分析方案/代码检查配置.md', - '/en/guide/分析方案/代码检查规则配置.md', - '/en/guide/分析方案/代码检查编译配置.md', - '/en/guide/分析方案/代码度量配置.md', - '/en/guide/分析方案/过滤配置.md', - '/en/guide/分析方案/分析方案模板说明.md', - ] - }, - { - text: '工具管理', - children: [ - '/en/guide/工具管理/工具管理说明.md', - '/en/guide/工具管理/自定义规则.md', - '/en/guide/工具管理/自定义工具.md', - ] - }, - { - text: '后台管理', - children: [ - '/en/guide/后台管理/用户管理.md', - '/en/guide/后台管理/团队管理.md', - '/en/guide/后台管理/项目管理.md', - '/en/guide/后台管理/分析记录管理.md', - '/en/guide/后台管理/节点管理.md', - '/en/guide/后台管理/工具管理.md', - '/en/guide/后台管理/OAuth管理.md', - ] - }, - { - text: '客户端', - children: [ - '/en/guide/客户端/配置说明.md', - '/en/guide/客户端/本地分析.md', - '/en/guide/客户端/常驻节点分析.md', - ] - }, - { - text: '服务端', - children: [ - '/en/guide/服务端/server.md', - '/en/guide/服务端/deploy_with_minio.md', - ] - }, - { - text: 'Web端', - children: [ - '/en/guide/web/web.md', - '/en/guide/web/deploySource.md', - ] - }, - ], - '/en/advanced/': [ - { - text: '深入', - children: [ - '/en/advanced/任务分布式执行.md', - '/en/advanced/集成代码分析工具.md', - ], - } - ], - '/en/community/': [ - { - text: '社区资源', - children: [ - '/en/community/contribute.md', - '/en/community/pr.md', - '/en/community/changelog.md', - '/en/community/joingroup.md', - ] - }, - ], - '/en/api/': [ - { - text: 'API', - children: [ - '/en/api/README.md', - '/en/api/对象主要字段说明.md', - '/en/api/项目管理模块接口.md', - '/en/api/任务管理模块接口.md', - '/en/api/结果概览模块接口.md', - '/en/api/代码扫描数据模块接口.md', - '/en/api/代码度量数据模块接口.md', - ] - }, - ], - '/en/quickStarted/': [ - { - text: '快速入门', - link: '/en/quickStarted/deploySever.md', - // children: [ - // { - // text: '快速入门', - // link: '/en/quickStarted/deploySever.md', - // }, - // ], - }, - { - text: '依赖安装参考', - // collapsible: true, - children: [ - '/en/quickStarted/references/install_python37_on_centos.md', - '/en/quickStarted/references/install_python37_on_ubuntu.md', - '/en/quickStarted/references/install_mysql_on_centos.md', - '/en/quickStarted/references/install_redis_on_centos.md', - '/en/quickStarted/references/install_redis_from_source.md', - '/en/quickStarted/references/install_nginx_from_source.md', - ], - }, - { - text: '其他', - // collapsible: true, - children: [ - '/en/quickStarted/intro.md', - '/en/quickStarted/tools.md', - '/en/quickStarted/FAQ.md', - '/en/quickStarted/codeDeploy.md', - '/en/quickStarted/dockercomposeDeploy.md', - ], - }, - ], -} \ No newline at end of file diff --git a/web/packages/tca-document/.vuepress/configs/sidebar/index.ts b/web/packages/tca-document/.vuepress/configs/sidebar/index.ts deleted file mode 100644 index 520a20301..000000000 --- a/web/packages/tca-document/.vuepress/configs/sidebar/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './zh' -export * from './en' diff --git a/web/packages/tca-document/.vuepress/configs/sidebar/zh.ts b/web/packages/tca-document/.vuepress/configs/sidebar/zh.ts deleted file mode 100644 index 68f594c80..000000000 --- a/web/packages/tca-document/.vuepress/configs/sidebar/zh.ts +++ /dev/null @@ -1,150 +0,0 @@ -import type { SidebarConfig } from '@vuepress/theme-default' - -export const zh: SidebarConfig = { - '/zh/guide/': [ - { - text: '介绍', - children: [ - '/zh/guide/README.md', - '/zh/guide/快速入门/快速启动一次代码分析.md' - ], - }, - { - text: '团队管理', - children: [ - '/zh/guide/团队管理/团队管理.md', - '/zh/guide/团队管理/成员权限.md', - '/zh/guide/团队管理/节点管理.md', - ] - }, - { - text: '代码检查', - children: [ - '/zh/guide/代码检查/分析结果查看.md', - ] - }, - { - text: '分析方案', - children: [ - '/zh/guide/分析方案/基础属性配置.md', - '/zh/guide/分析方案/代码检查配置.md', - '/zh/guide/分析方案/代码检查规则配置.md', - '/zh/guide/分析方案/代码检查编译配置.md', - '/zh/guide/分析方案/代码度量配置.md', - '/zh/guide/分析方案/过滤配置.md', - '/zh/guide/分析方案/分析方案模板说明.md', - ] - }, - { - text: '工具管理', - children: [ - '/zh/guide/工具管理/工具管理说明.md', - '/zh/guide/工具管理/自定义规则.md', - '/zh/guide/工具管理/自定义工具.md', - ] - }, - { - text: '后台管理', - children: [ - '/zh/guide/后台管理/用户管理.md', - '/zh/guide/后台管理/团队管理.md', - '/zh/guide/后台管理/项目管理.md', - '/zh/guide/后台管理/分析记录管理.md', - '/zh/guide/后台管理/节点管理.md', - '/zh/guide/后台管理/工具管理.md', - '/zh/guide/后台管理/OAuth管理.md', - ] - }, - { - text: '客户端', - children: [ - '/zh/guide/客户端/配置说明.md', - '/zh/guide/客户端/本地分析.md', - '/zh/guide/客户端/常驻节点分析.md', - ] - }, - { - text: '服务端', - children: [ - '/zh/guide/服务端/server.md', - '/zh/guide/服务端/deploy_with_minio.md', - ] - }, - { - text: 'Web端', - children: [ - '/zh/guide/web/web.md', - '/zh/guide/web/deploySource.md', - ] - }, - ], - '/zh/advanced/': [ - { - text: '深入', - children: [ - '/zh/advanced/任务分布式执行.md', - '/zh/advanced/集成代码分析工具.md', - ], - } - ], - '/zh/community/': [ - { - text: '社区资源', - children: [ - '/zh/community/contribute.md', - '/zh/community/pr.md', - '/zh/community/changelog.md', - '/zh/community/joingroup.md', - ] - }, - ], - '/zh/api/': [ - { - text: 'API', - children: [ - '/zh/api/README.md', - '/zh/api/对象主要字段说明.md', - '/zh/api/项目管理模块接口.md', - '/zh/api/任务管理模块接口.md', - '/zh/api/结果概览模块接口.md', - '/zh/api/代码扫描数据模块接口.md', - '/zh/api/代码度量数据模块接口.md', - ] - }, - ], - '/zh/quickStarted/': [ - { - text: '快速入门', - link: '/zh/quickStarted/deploySever.md', - // children: [ - // { - // text: '快速入门', - // link: '/zh/quickStarted/deploySever.md', - // }, - // ], - }, - { - text: '依赖安装参考', - // collapsible: true, - children: [ - '/zh/quickStarted/references/install_python37_on_centos.md', - '/zh/quickStarted/references/install_python37_on_ubuntu.md', - '/zh/quickStarted/references/install_mysql_on_centos.md', - '/zh/quickStarted/references/install_redis_on_centos.md', - '/zh/quickStarted/references/install_redis_from_source.md', - '/zh/quickStarted/references/install_nginx_from_source.md', - ], - }, - { - text: '其他', - // collapsible: true, - children: [ - '/zh/quickStarted/intro.md', - '/zh/quickStarted/tools.md', - '/zh/quickStarted/FAQ.md', - '/zh/quickStarted/codeDeploy.md', - '/zh/quickStarted/dockercomposeDeploy.md', - ], - }, - ], -} \ No newline at end of file diff --git a/web/packages/tca-document/.vuepress/public/images/Logo.svg b/web/packages/tca-document/.vuepress/public/images/Logo.svg deleted file mode 100644 index 5a9af40da..000000000 --- a/web/packages/tca-document/.vuepress/public/images/Logo.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - logo-1280-2 - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/packages/tca-document/.vuepress/public/images/favicon.png b/web/packages/tca-document/.vuepress/public/images/favicon.png deleted file mode 100644 index d23675e16..000000000 Binary files a/web/packages/tca-document/.vuepress/public/images/favicon.png and /dev/null differ diff --git a/web/packages/tca-document/.vuepress/styles/index.scss b/web/packages/tca-document/.vuepress/styles/index.scss deleted file mode 100644 index cbac022c5..000000000 --- a/web/packages/tca-document/.vuepress/styles/index.scss +++ /dev/null @@ -1,17 +0,0 @@ -:root { - scroll-behavior: smooth; - --c-brand: #176de6; - --c-brand-light: #257efa; - .home .hero .description { - font-size: 18px; - } -} - -html.dark { - --c-brand: #257efa; - --c-brand-light: #176de6; -} - -.home .hero img { - max-height: 200px; -} diff --git a/web/packages/tca-document/README.md b/web/packages/tca-document/README.md deleted file mode 100644 index cee92ccde..000000000 --- a/web/packages/tca-document/README.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -home: true -title: 腾讯云代码分析文档 -heroImage: /images/Logo.svg -actions: - - text: 快速入门 - link: /zh/quickStarted/deploySever.html - type: primary - - text: 帮助文档 - link: /zh/guide/ - type: secondary -features: - - title: 稳定可靠的架构 - details: 支持分布式云原生计算架构,支持灵活扩缩容,执行更快更稳定。 - - title: 多工具支持 - details: 已集成众多自研、知名开源工具等,采用分层分离架构,可满足团队快速自助管理工具。 - - title: 多语言覆盖 - details: 支持 Java/C++/Objective-C/C#/JavaScript/Python/Go/PHP 等数29种语言,覆盖常用编程语言。 - - title: 增量全量分析 - details: 增量分析快速发现问题,全量分析保证问题全覆盖。 - - title: 自定义指标 - details: 自定义代码标准,逐步优化代码。 - - title: 全方位质量报告 - details: 图形化可视报告,轻松监管代码综合质量趋势。 - - title: 全方位质量报告 - details: 图形化可视报告,轻松监管代码综合质量趋势。 - - title: 标准化 API 接口 - details: 提供标准化 API 接口,支持快速对接 DevOps 平台。 - - title: 分布式客户端 - details: 支持分布式客户端,包含 Linux、Mac、Windows,满足用户本地高频分析场景。 -footer: MIT Licensed | Copyright © 1998-present Tencent. All Rights Reserved. ---- - -### 腾讯工蜂代码库镜像库 - -[https://git.code.tencent.com/Tencent_Open_Source/CodeAnalysis.git](https://git.code.tencent.com/Tencent_Open_Source/CodeAnalysis.git) - -### 腾讯云代码分析简介 - -腾讯云代码分析(Tencent Cloud Code Analysis,简称TCA,内部曾用研发代号 **CodeDog** )是集众多分析工具的云原生、分布式、高性能的代码综合分析跟踪平台,包含服务端、Web端和客户端三个组件,已集成一批自研工具,同时也支持动态集成业界各编程语言的分析工具。 - -代码分析是通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,对代码进行综合分析,验证代码是否满足规范性、安全性、可靠性、可维护性等指标的一种代码分析技术。 - -使用TCA可以帮助团队用代码分析技术查找代码中的规范性、结构性、安全漏洞等问题,持续监控项目代码质量并进行告警。同时TCA开放API,支持与上下游系统对接,从而集成代码分析能力,为代码质量提供保障,更有益于传承优良的团队代码文化。 - -![组件图](https://tencent.github.io/CodeAnalysis/media/Components.png) - -![流程图](https://tencent.github.io/CodeAnalysis/media/Flow.png) - -### 体验 - -[官方版本](http://tca.tencent.com) - -### 快速入门 - -- [快速入门](./zh/quickStarted/intro.md) -- [如何在本地部署Server与Web](./zh/quickStarted/deploySever.md#通过源代码) -- [如何通过Docker-Compose部署Server与Web](./zh/quickStarted/deploySever.md#通过docker-compose) -- [如何使用客户端](./zh/quickStarted/deployClient.md) -- [部署常见问题与解决方式](./zh/quickStarted/FAQ.md) - -## 社区 - -- 微信公众号:「腾讯云静态分析」,关注并发送“进群”即可加入官方开源交流微信群 -- QQ交流群:361791391 -- [GitHub讨论区](https://github.com/Tencent/CodeAnalysis/discussions) -- [Wiki](https://github.com/Tencent/CodeAnalysis/wiki) -- [腾讯云代码分析白皮书](https://github.com/Tencent/CodeAnalysis/tree/main/腾讯云代码分析白皮书.pdf) - -## 更新日志 - -[Changelog](https://github.com/Tencent/CodeAnalysis/tree/main/CHANGELOG.md) - -## 贡献 - -- 查看我们的[贡献说明](https://github.com/Tencent/CodeAnalysis/tree/main/CONTRIBUTING.md) -- [腾讯开源摘星计划2022](https://github.com/weopenprojects/WeOpen-Star/issues/19#issue-1228583868)(活动时间:2022年5月~12月) -- [腾讯开源激励计划](https://opensource.tencent.com/contribution) 鼓励开发者的参与和贡献,期待你的加入 - -### License - -[MIT licensed](https://github.com/Tencent/CodeAnalysis/tree/main/LICENSE) diff --git a/web/packages/tca-document/en/README.md b/web/packages/tca-document/en/README.md deleted file mode 100644 index e698dd0cd..000000000 --- a/web/packages/tca-document/en/README.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -home: true -title: 腾讯云代码分析文档 -heroImage: /images/Logo.svg -actions: - - text: 快速入门 - link: /zh/quickStarted/deploySever.html - type: primary - - text: 帮助文档 - link: /zh/guide/ - type: secondary -features: - - title: 稳定可靠的架构 - details: 支持分布式云原生计算架构,支持灵活扩缩容,执行更快更稳定。 - - title: 多工具支持 - details: 已集成众多自研、知名开源工具等,采用分层分离架构,可满足团队快速自助管理工具。 - - title: 多语言覆盖 - details: 支持 Java/C++/Objective-C/C#/JavaScript/Python/Go/PHP 等数29种语言,覆盖常用编程语言。 - - title: 增量全量分析 - details: 增量分析快速发现问题,全量分析保证问题全覆盖。 - - title: 自定义指标 - details: 自定义代码标准,逐步优化代码。 - - title: 全方位质量报告 - details: 图形化可视报告,轻松监管代码综合质量趋势。 - - title: 全方位质量报告 - details: 图形化可视报告,轻松监管代码综合质量趋势。 - - title: 标准化 API 接口 - details: 提供标准化 API 接口,支持快速对接 DevOps 平台。 - - title: 分布式客户端 - details: 支持分布式客户端,包含 Linux、Mac、Windows,满足用户本地高频分析场景。 -footer: MIT Licensed | Copyright © 1998-present Tencent. All Rights Reserved. ---- - -### Repo Mirror - -[https://git.code.tencent.com/Tencent_Open_Source/CodeAnalysis.git](https://git.code.tencent.com/Tencent_Open_Source/CodeAnalysis.git) - -### What is TCA - -Tencent Cloud Code Analysis (TCA for short, code-named **CodeDog** inside the company early) is a comprehensive platform for code analysis and issue tracking. TCA consist of three components, server, web and client. It integrates of a number of self-developed tools, and also supports dynamic integration of code analysis tools in various programming languages. - -Code analysis is a technology, using lexical analysis, syntax analysis, control-flow analysis, data-flow analysis to make a comprehensive analysis of the code, so as to verify whether the code meets the requirements of normative, security, reliability, maintainability and other indicators. - -Using TCA can help team find normative, structural, security vulnerabilities and other issues in the code, continuously monitor the quality of the project code and issue alerts. At the same time, TCA opens up APIs to support connection with upstream and downstream systems, so as to integrate code analysis capabilities, ensure code quality, and be more conducive to inheriting an excellent team code culture. - -![组件图](https://tencent.github.io/CodeAnalysis/media/Components.png) - -![流程图](https://tencent.github.io/CodeAnalysis/media/Flow.png) - -### Experience - -[Experience Link](http://tca.tencent.com) - -### Getting Started - -- [How to get start](./quickStarted/intro.md) -- [How to deploy server and web](./quickStarted/deploySever.md#通过源代码) -- [How to deploy server and web with docker-compose](./quickStarted/deploySever.md#通过docker-compose) -- [How to use client](./quickStarted/deployClient.md) -- [Deploy Q&A](./quickStarted/FAQ.md) - -### Community - -- WeChat official account:腾讯云静态分析 -- QQ Group: 361791391 -- [Discussion](https://github.com/Tencent/CodeAnalysis/discussions) -- [Wiki](https://github.com/Tencent/CodeAnalysis/wiki) -- [White Paper](https://github.com/Tencent/CodeAnalysis/tree/main/腾讯云代码分析白皮书.pdf) - -### Changelogs - -- Check our [Changelog](https://github.com/Tencent/CodeAnalysis/tree/main/CHANGELOG.md) - -### Contributing - -- Check out [CONTRIBUTING](https://github.com/Tencent/CodeAnalysis/tree/main/CONTRIBUTING.md) to see how to develop with TCA. -- [Tencent WeOpen Star Project](https://github.com/weopenprojects/WeOpen-Star/issues/19#issue-1228583868)(From May 2022 to September 2022) -- [Tencent Open Source Incentive Program](https://opensource.tencent.com/contribution) encourages the participation and contribution of developers. We look forward to your active participation. - -### License - -TCA is [MIT licensed](https://github.com/Tencent/CodeAnalysis/tree/main/LICENSE) diff --git "a/web/packages/tca-document/en/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" "b/web/packages/tca-document/en/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" deleted file mode 100644 index 5af9d5ac8..000000000 --- "a/web/packages/tca-document/en/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" +++ /dev/null @@ -1,71 +0,0 @@ -# 任务分布式执行 - -## 适用场景 - -- 以往的单机器单进程,性能比较低,工具排队等待时间过长。希望通过并行执行分析来提高分析效率。 - -- 希望尽量使用公共资源或使用专机资源。 - -**为了满足以上需求,TCA已经进行如下支持:** - -- 支持工具在多台机器上并行执行。 - -- 支持指定工具在指定的机器上运行。 - -- 支持与本地启动的任务衔接,加速本地任务扫描。 - -- 配套任务状态监控能力,及时重置初始化超时或机器掉线的任务。 - -:::tip -TCA客户端除了通过localscan命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。和本地分析一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -## 常驻节点配置 - -**前置步骤**:公共/专有机器上已具备客户端。 - -开源版客户端,需要配置相关环境和依赖,可查阅帮助文档中的开源版客户端使用说明(如下图) - - ![helpopensource](https://tencent.github.io/CodeAnalysis/media/helpopensource.png) - (界面右上角图标点击-帮助文档-Client 客户端) - -**1.配置 config.ini 文件** - -将``替换成实际的serve ip(可包含端口号)。 - -**2.启动代码分析常驻节点** - -1. 从TCA前端页面中获取 `token`,前往 个人中心-个人令牌-复制`Token` 。 - - **作为公共节点**:`token`需要具有超级管理员权限(界面右上角图标点-管理入口-用户管理),如使用CodeDog账户的`token`。 - - - **作为专机节点**:该节点仅能分析该token具有权限的项目。 - -2. 进入到client目录下,执行命令: - `python3 codepuppy.py -l codepuppy.log start -t ` - - ![order](https://tencent.github.io/CodeAnalysis/media/order.png) - -3. 启动后,可以在命令行输出或codepuppy.log中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -**3.配置节点** - -:::tip -常驻节点首次启动后,需要到节点管理页面设置节点状态(默认为不可用),将其设置为活跃,用于接收和执行任务。 -::: - -1. 进入TCA节点管理页面。可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 - - ![NodeManagement](https://tencent.github.io/CodeAnalysis/media/Nodemanagement.png) - (界面右上角图标点击-管理入口-节点管理) - -- 常驻节点首次启动后,需将节点状态从不可用(失效)状态切换到活跃(在线)状态。 - - ![StateSwitch](https://tencent.github.io/CodeAnalysis/media/StateSwitch.png) - -- 可以进入工具进程配置页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 - - ![ProcessConfiguration](https://tencent.github.io/CodeAnalysis/media/ProcessConfiguration.png) - -- 节点所属标签会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 - -本功能代码已提交开源版,欢迎使用! :+1: diff --git "a/web/packages/tca-document/en/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" "b/web/packages/tca-document/en/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" deleted file mode 100644 index ca4463fe8..000000000 --- "a/web/packages/tca-document/en/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" +++ /dev/null @@ -1,215 +0,0 @@ -# 集成代码分析工具 - -## 初识TCA任务执行机制 - -1. TCA server在接收到开启分析的请求后根据所选规则生成对应的task_request,每个task_request对应一个工具的任务 -2. TCA server将`task_request`分发到能够执行该工具的机器 -3. TCA client在收到task_request后提取出本次任务的工具名也就是其中的`task_name`字段,字段对应于工具的`name`字段 -4. TCA client按照`task_name`在client中的tool目录查找对应python启动脚本 -5. 执行python启动脚本中的内容 - -## 添加分析工具(以tca_ql_php_beta为例) - -根据上述的任务机制添加工具需要做到以下几点 - -1. 让server知道存在`tca_ql_php_beta`工具及其所含的规则 -2. 让server知道哪些客户端可以执行`tca_ql_php_beta`工具 -3. client下载/找到工具所在目录及需要的环境 -4. 让client知道`tca_ql_php_beta`对应的启动脚本是什么 - -### 如何让Server知道存在相应工具 - -1. 找到`server/projects/main/apps/scan_conf/management/commands/open_source`目录 - -2. 创建工具json文件,json文件名尽量对应工具名称方便查看 - -3. json文件内容为(以tca_ql_php_beta为例) - - ```python - [ - { - "name": "tca_ql_php_beta", - "display_name": "Hades_Beta_PHP(展示名称用于前端展示使用)", - "description": "工具描述", - "license": "工具license", - "libscheme_set": [], # 暂时不需要 - "task_processes": [ - "analyze", - "datahandle", - "compile" - ], # 工具进程,包含compile编译, analyze分析, datahandle数据处理 - "scan_app": "codelint", # 代码分析统一为codelint - "scm_url": "", # 暂时为空 - "run_cmd": "", - "envs": null, # 是否需要特殊环境,这里无需填写 - "build_flag": false, # 是否需要编译命令才能运行 - "checkrule_set": [ # 工具包含的规则 - { - "real_name": "deser", # 规则名 - "display_name": "反序列化漏洞", # 规则前端展示,考虑各工具规则名可能晦涩难懂,设置展示名称方便查找 - "severity": "error", # 规则等级 从上到下分为 fatal, error, warning, info 四个等级 - "category": "security", # 规则类别。correctness 功能 security安全 performance性能 usability可用性 accessibility无障碍化 i18n国际化 convention代码风格 other其他 - "rule_title": "反序列化漏洞", # 一句话概括规则简介 - "rule_params": null, # 规则参数 - "languages": [ # 支持语言 - "php" - ], - "solution": "", # 建议的解决方法 - "owner": "", - "labels": [], - "description": "", # 规则详细介绍 - } - ] - } - ] - ``` - -4. 在`server/projects/main/`目录执行`python manage.py loadcheckers --dir open_source tca_ql_php_beta` 加载工具进入数据库 - -## 让server知道哪些客户端可以执行`tca_ql_php_beta`工具 - -1. 进入节点管理页面 - -![节点管理](https://tencent.github.io/CodeAnalysis/media/node_mange.png) - -2. 选择其中一台机器 工具进程配置,勾选其工具进程 - -![工具进程](https://tencent.github.io/CodeAnalysis/media/tool.png) - -## client下载/找到工具所在目录及需要的环境 - -1. 找到puppy-tool-config若没有额外配置则为默认代码库 -2. 修改其中的 ini 配置文件,每个操作系统对应一个ini -3. 以tca_ql_php_beta为例需要做以下修改 - -``` -; env_path 主要填写存放工具文件所在的相对目录,一般都存放/拉取在tools下,会在工具执行前加载到环境变量中提供使用 -[env_path] -ZEUS_BETA_HOME : Zeus_Beta -HADES_BETA_HOME : Hades_Beta - -; toolz_url -[tool_url] 主要填写工具的git仓库,这里因为tca_ql_php_beta直接使用tools下的目录所以不用再进行额外拉取也无需再写 -CPPCHECK : ${base_value:git_url}/linux-cppcheck-1.78 - -; 各工具配置 以tca_ql_php_beta为例 -; env_path 填写上面需要加载的环境变量 -; env_value 通用环境变量,一般无需填写如果有需求需要现在 [env_value] 中定义好再填写 -; path 工具所在目录填写上面的定义 -; tool_url 工具git仓库,使用本地相对目录故为空 -[tca_ql_php_beta] -env_path : ZEUS_BETA_HOME;HADES_BETA_HOME -env_value : -path : ${env_path:ZEUS_BETA_HOME};${env_path:HADES_BETA_HOME} -tool_url : - -``` - -## 让client知道`tca_ql_php_beta`对应的启动脚本是什么 - -1. 以上述步骤在`client/tool`目录添加脚本`tca_ql_php_beta.py`作为启动脚本 注:启动脚本必须与工具名称相同 - -2. 编写脚本 - -### 脚本编写规范 - -以`tca_ql_php_beta`为例 - -``` - -from task.codelintmodel import CodeLintModel -from util.logutil import LogPrinter -from util.subprocc import SubProcController - -logger = LogPrinter() - - -class TcaQlPHPBeta(CodeLintModel): - # 代码分析工具集成基类CodeLintModel - def __init__(self, params): - logger.info("找到工具了Q_Q") - super().__init__(params) - - def compile(self, params): - logger.info("开始编译了Q_Q") - build_cmd = params.get('build_cmd', None) # 从params中获取编译命令, params内容可以在最后附录查看 - lang = "php" - do_some_things() - - def analyze(self, params): - logger.info("开始分析了Q_Q") - lang = "php" - HADES_HOME = envs.get("HADES_BETA_HOME", None) - output_json = "result.json" - sp = SubProcController( - command=["Hades", "analyze", "test.php", "-o", output_json], - cwd=HADES_HOME, - stdout_line_callback=subprocc_log, - stderr_line_callback=subprocc_log, - ) - sp.wait() # 执行工具分析命令 - issues = [] - # 工具结果输出到output_json,具体工具可能有所不同 - if os.path.exists(output_json): - with open(output_json, "r") as result_reader: - result = json.load(result_reader) - issues.extend(result) - return issues - -tool = TcaQlPHPBeta # 必须,必须包含tool变量并且为该工具的类 -``` - -1. 脚本必须包含analyze方法,如果有配置编译进程也需要相应的compile方法来做编译相关工作,datahandle函数不用自定义基类方法已经够用了。方法执行顺序为 compile -> analyze -> datahandle -2. params参数为`task_request`中的`task_params`字段,具体字段将在最后附录进行说明 -3. anlyze方法必须有返回值,返回值为issue列表,issue格式为 - -``` -{ - "path": "文件相对路径", - "line": "行号,int类型", - "column": "列号, int类型,如果工具没有输出列号信息,可以用0代替", - "msg": "提示信息", - "rule": "规则名称,可以根据需要输出不同的规则名", - "refs": [ - { - "line": "回溯行号", - "msg": "提示信息", - "tag": "用一个词简要标记该行信息,比如uninit_member,member_decl等,如果没有也可以都写成一样的", - "path": "回溯行所在文件绝对路径" - }, - ... - ] -} -说明: - refs:可选,记录问题回溯路径信息。比如当前文件的回溯路径其他的3行代码,可以将这三行的路径及提示信息,按顺序添加到refs数组中。 -``` - -# PR - -如果有意公开您添加的工具欢迎发起PR - -注:别忘了puppy-tool-config 也需要PR - -# 附录 - -## params 表格 - -| 字段 | 说明 | 类型 | -| --- | --- | --- | -| scan_languages | 语言 | 字符串列表如 ["python", "php"] | -| pre_cmd | 编译前置命令 | 字符串 | -| build_cmd | 编译命令 | 字符串 | -| envs | 额外环境变量 | 字符串 | -| scm_last_revision | 上次成功分析的代码版本,增量使用 | 字符串 | -| incr_scan | 是否为增量分析 | bool | -| rules | 规则名称列表,只有规则名 | 字符串列表 | -| rule_list | 详细的规则列表包含规则名和规则参数等 | 字典列表 | -| checktool | 工具详细信息,执行一般用不到 | 字典 | -| path_filters | 过滤路径 | 字典 | -| scm_url | 代码库url | 字符串 | -| source_dir | 代码库本地目录 | 字符串 | -| work_dir | 本次任务的work_dir目录 | 字符串 | -| project_id | 分析项目id | int | -| repo_id | 仓库id | int | -| task_id | 任务id | int | -| job_id | 本次分析的id | int | diff --git a/web/packages/tca-document/en/api/README.md b/web/packages/tca-document/en/api/README.md deleted file mode 100644 index 701f35131..000000000 --- a/web/packages/tca-document/en/api/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# 接口调用说明 - -## 接口地址 - -`http://{host}/server/` - -注:host 指当前浏览器访问该文档的 URL 域名部分。 - -## 接口鉴权方式 - -发起请求时,需要在头部中添加以下格式形式,对应的 value 请看下面获取方式 - -```json -{ - "Authorization": "当前user的token" -} -``` - -获取 token 位置(个人中心-个人令牌): - -![API的个人令牌](../../images/API的个人令牌.png) - -## 获取 org_sid 和 project_team 信息 - -通过平台访问具体代码库扫描情况时,可从 URL 中获取对应 org_sid 和 project_team 字段,查看方式如下例子: - -代码库扫描地址:`http://{host}/t/xxx/p/yyy/code-analysis/repos/1/projects?limit=10&offset=0` - -其中,org_sid 为`xxx`字段,project_team 为 `yyy`字段 - -## Example - -```python -import requests -# 假设: -# 当前域名为http://tca.com/,当前org_sid为helloworld -# 获取helloworld团队下的hellotca项目下登记的代码库 -url="http://tca.com/server/main/api/orgs/helloworld/teams/hellotca/repos/?limit=12&offset=0" -headers = { - "Authorization": token, -} - -response = requests.get(url, headers=headers) -print(response.json()) -# 结果如下: -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 23, - "name": "repo_name", - "scm_url": "http://git.repo.com/group/repo_name", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-05-14 02:34:44.509118+00:00", - "recent_active": { - "id": 27, - "branch_name": "master", - "active_time": "2021-05-14 02:34:44.509118+00:00", - "total_line_num": 1, - "code_line_num": 1 - }, - "created_from": "tca", - "creator": { - "username": "author", - "nickname": "author", - "status": 1, - "avatar": "url", - "org": "org_name" - }, - "symbol": null, - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "test", - "scm_platform": 2, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": "url", - "org": "org_name" - } - }, - "auth_type": "ssh_token", - "created_time": "2021-05-14T10:34:44.552859+08:00", - "modified_time": "2021-05-14T10:34:44.552887+08:00" - }, - "project_team": { - "name": "test", - "display_name": "测试", - "status": 1, - "org_sid": "test" - } - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 分页方式 - -平台返回的数据分页格式是使用`limit`和`offset`参数进行分页处理 - -比如:`server/main/api/orgs//teams/?limit=12&offset=12`获取得到的数据是从第 13 条开始获取 diff --git "a/web/packages/tca-document/en/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/en/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 5a8befdb9..000000000 --- "a/web/packages/tca-document/en/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,708 +0,0 @@ -# 代码度量数据管理 - -## 查看指定项目的圈复杂度文件列表 - -```bash -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| scan_open | int | 发现问题的扫描编号 | -| scan_close | int | 修复问题的扫描编号 | -| worse | boolean | 圈复杂度是否恶化 | -| over_cc_sum_gte | int | 圈复杂度总和最小值 | -| over_cc_sum_lte | int | 圈复杂度总和最大值 | -| over_cc_avg_gte | int | 平均圈复杂度最小值 | -| over_cc_avg_lte | int | 平均圈复杂度总和最大值 | -| over_cc_func_count_gte | int | 超标圈复杂度函数个数最小值 | -| over_cc_func_count_lte | int | 超标圈复杂度函数个数最大值 | - -#### 返回参数 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的圈复杂度文件问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccfiles//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的圈复杂度问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度文件列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_close_id | int | 修复问题的扫描编号 | -| worse | boolean | 圈复杂度是否恶化 | -| over_cc_sum_gte | int | 圈复杂度总和最小值 | -| over_cc_sum_lte | int | 圈复杂度总和最大值 | -| over_cc_avg_gte | int | 平均圈复杂度最小值 | -| over_cc_avg_lte | int | 平均圈复杂度总和最大值 | -| over_cc_func_count_gte | int | 超标圈复杂度函数个数最小值 | -| over_cc_func_count_lte | int | 超标圈复杂度函数个数最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 32, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "tapd_url": null, - "created_time": "2020-06-02T10:59:09.418250+08:00", - "creator": null, - "modified_time": "2020-06-03T16:17:40.892224+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "over_func_cc": 0, - "over_cc_sum": 0, - "over_cc_avg": 0, - "over_cc_func_count": 0, - "diff_over_func_cc": 0, - "diff_over_cc_sum": 0, - "diff_over_cc_avg": 0, - "diff_over_cc_func_count": 0, - "worse": false, - "file_path": "test/demo.py", - "state": 3, - "change_type": 0, - "last_modifier": "author1", - "author": null, - "related_modifiers": "author1;author2", - "file_owners": null, - "language": "python", - "tapd_ws_id": null, - "tapd_bug_id": null, - "revision": null, - "ci_time": null, - "project": 1, - "scan_open": 1, - "scan_close": 2 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度文件问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccfiles//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的重复文件列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| issue__state | str | 问题状态, 1为未处理,2为可忽略,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 重复文件更改类型,add为新增,del为删除,mod为删除,可多选,格式为add,del,mod | -| issue__owner | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| duplicate_rate_gte | int | 重复率最小值 | -| duplicate_rate_lte | int | 重复率最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "issue": { - "id": 1, - "state": 1, - "owner": "author" - }, - "project_id": 1, - "scan_id": 1, - "issue_id": 1, - "issue_state": 1, - "issue_owner": "author", - "dir_path": "test", - "file_name": "demo.py", - "file_path": "test/demo.py", - "duplicate_rate": 4.63, - "total_line_count": 259, - "total_duplicate_line_count": 12, - "distinct_hash_num": 1, - "block_num": 1, - "last_modifier": "author", - "change_type": null, - "scm_revision": "12345678abc", - "is_latest": true - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定重复文件 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles// -``` - -#### 返回结果 - -```JSON -{ - "data": { - "id": 1, - "repo": 1, - "issue": { - "id": 1, - "state": 1, - "owner": "author" - }, - "blocks": [ - { - "id": 1, - "duplicate_file": 1, - "project_id": 1, - "scan_id": 1, - "duplicate_file_id": 1, - "token_num": 120, - "duplicate_times": 2, - "duplicate_rate": 4.63, - "start_line_num": 216, - "end_line_num": 227, - "duplicate_line_count": 12, - "last_modifier": "author", - "change_type": null, - "related_modifiers": "author" - } - ], - "duplicate_rate_trend": 0.0, - "project_id": 1815, - "scan_id": 488, - "issue_id": 3, - "issue_state": 1, - "issue_owner": "author", - "dir_path": "test", - "file_name": "demo.py", - "file_path": "test/demo.py", - "duplicate_rate": 4.63, - "total_line_count": 259, - "total_duplicate_line_count": 12, - "distinct_hash_num": 1, - "block_num": 1, - "last_modifier": "author", - "change_type": null, - "scm_revision": "xxx", - "is_latest": true - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定文件的重复块列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles//blocks/ -``` - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "duplicate_file": 1, - "project_id": 1, - "scan_id": 1, - "duplicate_file_id": 1, - "token_num": 120, - "duplicate_times": 2, - "duplicate_rate": 4.63, - "start_line_num": 216, - "end_line_num": 227, - "duplicate_line_count": 12, - "last_modifier": "author", - "change_type": null, - "related_modifiers": "author" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的文件行数列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/clocfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| change_type | str | 改变类型(add、mod、del),支持多值,使用英文逗号','分隔 | -| file_path | str | 文件路径 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": "", - "previous": null, - "results": [ - { - "id": 1, - "code_line_num": 108587, - "comment_line_num": 0, - "blank_line_num": 0, - "total_line_num": 108587, - "add_code_line_num": 108587, - "add_comment_line_num": 0, - "add_blank_line_num": 0, - "add_total_line_num": 108587, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1, - "scan_id": 1, - "is_latest": true, - "dir_path": "test", - "file_name": "test.json", - "language": "JSON", - "change_type": "add" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的语言列表 - -``` -GET server/analysis/api/orgs//teams//repos//projects//codemetric/cloclangs/ -``` - -#### 返回结果 - -```JSON -{ - "data": { - "count": 2, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "code_line_num": 9753, - "comment_line_num": 4220, - "blank_line_num": 2454, - "total_line_num": 16427, - "add_code_line_num": 9753, - "add_comment_line_num": 4220, - "add_blank_line_num": 2454, - "add_total_line_num": 16427, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1815, - "scan_id": 695, - "is_latest": true, - "name": "Python", - "file_num": 165 - }, - { - "id": 2, - "code_line_num": 379, - "comment_line_num": 0, - "blank_line_num": 153, - "total_line_num": 532, - "add_code_line_num": 379, - "add_comment_line_num": 0, - "add_blank_line_num": 153, - "add_total_line_num": 532, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1815, - "scan_id": 695, - "is_latest": true, - "name": "Markdown", - "file_num": 7 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` diff --git "a/web/packages/tca-document/en/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/en/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index fc89e3982..000000000 --- "a/web/packages/tca-document/en/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,274 +0,0 @@ -# 代码扫描数据管理 - -## 查看扫描问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/issues/ -``` - -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open | int | 发现问题的扫描编号 | -| scan_fix | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间,格式为"2021-01-01 00:00:00" | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "file_path": "test/demo.py", - "project": 1, - "repo": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checktool_name": "xxx", - "msg": "xxx", - "state": 3, - "resolution": 1, - "author": "author", - "author_email": null, - "severity": 2, - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "file_owners": null, - "is_external": false, - "scm_url": "", - "real_file_path": "", - "scan_open": 1, - "scan_fix": 2, - "fixed_time": "2021-02-19T15:25:15.152350+08:00" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看问题详情 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/issues// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "issue_details": [ - { - "id": 1, - "issue_refers": [], - "creator": null, - "modifier": null, - "deleted_time": null, - "deleter": null, - "issuedetail_uuid": "0fcc376e-7283-11eb-bd53-5254005e71ca", - "checkrule_real_name": "xxx", - "checktool_name": "xxx", - "author": "author", - "author_email": null, - "line": 1809, - "column": 15, - "scan_revision": "scan_revision", - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "real_revision": "", - "created_time": "2021-02-19T15:21:19.625658+08:00", - "modified_time": "2021-02-19T15:21:19.625662+08:00", - "issue": null, - "project": 1 - } - ], - "is_external": false, - "repo": 1, - "author": "author", - "created_time": "2021-02-19T15:21:19.625685+08:00", - "creator": null, - "modifier": null, - "deleted_time": null, - "deleter": null, - "file_path": "test/demo.py", - "file_hash": "xxx", - "scm_url": "", - "real_file_path": "", - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "state": 3, - "resolution": 1, - "scan_revision": null, - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "file_owners": null, - "fixed_time": "2021-02-19T15:25:15.152350+08:00", - "tapd_ws_id": null, - "tapd_bug_id": null, - "modified_time": "2021-02-19T15:25:17.807478+08:00", - "project": 1, - "scan_open": 1, - "scan_fix": 2 - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` - -## 查看每次扫描的问题列表 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/scans//issues/ -``` -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_fix_id | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间 | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo_id": 1, - "project_id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "file_path": "test/demo.py", - "scm_url": "", - "real_file_path": "", - "line": 21, - "column": 68, - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "msg": "xxx", - "state": 1, - "resolution": null, - "author": "author", - "scan_open_id": 1, - "scan_fix_id": null, - "issuedetail_uuid": "26d7ba88-8268-11eb-a304-5254005e71ca", - "scan_revision": "scan_revision", - "real_revision": "", - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2019-07-01T10:28:19+08:00", - "file_owners": null, - "created_time": "2021-03-11T20:49:00.539537+08:00", - "fixed_time": null - } - ] - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` - - -## 查看指定CR扫描的问题列表 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/crscans//issues/ -``` -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_fix_id | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间 | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo_id": 1, - "project_id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "file_path": "test/demo.py", - "scm_url": "", - "real_file_path": "", - "line": 21, - "column": 68, - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "msg": "xxx", - "state": 1, - "resolution": null, - "author": "author", - "scan_open_id": 1, - "scan_fix_id": null, - "issuedetail_uuid": "26d7ba88-8268-11eb-a304-5254005e71ca", - "scan_revision": "scan_revision", - "real_revision": "", - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2019-07-01T10:28:19+08:00", - "file_owners": null, - "created_time": "2021-03-11T20:49:00.539537+08:00", - "fixed_time": null - } - ] - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` \ No newline at end of file diff --git "a/web/packages/tca-document/en/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/en/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 54e3b6a3d..000000000 --- "a/web/packages/tca-document/en/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,132 +0,0 @@ -# 任务管理模块 - -## 执行指定代码库指定分支项目扫描任务 - -``` -POST /server/main/api/orgs//teams//repos//projects//scans/create/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| incr_scan | bool | 增量扫描标志,true表示增量,false表示全量 | -| async_flag | bool | 异步启动标志,true表示异步,false表示同步,建议选择异步 | -| force_create | bool | 强制启动标志,true表示强制启动,不等待上一个任务结束 | - -#### 返回结果 -```JSON -{ - "job": { - "id": 7974 - }, - "scan": { - "id": 5528 - } -} -``` - -## 查看指定项目的任务列表 -``` -GET /server/main/api/orgs//teams//repos//projects//jobs/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| create_time_gte | datetime | 最小任务启动时间 | -| create_time_lte | datetime | 最大任务启动时间 | -| result_code_gte | int | 最小错误码值 | -| result_code_lte | int | 最大错误码值 | -| result_msg | str | 结果信息 | -| state | int | 任务状态, 0为等待中,1为执行中,2为关闭,3为入库中,可多选,格式为1,2,3 | -| created_from | str | 创建来源 | -| creator | str | 创建用户 | - - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "state": 2, - "result_code": 0, - "result_msg": "success", - "code_line_num": 1000, - "comment_line_num": 5, - "blank_line_num": 305, - "total_line_num": 1400 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定任务详情 - -``` -GET /server/main/api/orgs//teams//repos//projects//jobs//detail/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "scan_id": 1, - "create_time": "2021-01-28T10:27:26.442961+08:00", - "waiting_time": "1", - "start_time": "2021-01-28T11:14:56.760427+08:00", - "execute_time": "3", - "project": { - "id": 1, - "branch": "master", - "repo_id": 1, - "scan_scheme": 1, - "repo_scm_url": "http://github.com/xxx/test_demo.git" - }, - "end_time": "2021-01-28T11:14:59.760427+08:00", - "expire_time": "2021-01-28T14:07:52.968932+08:00", - "task_num": 1, - "task_done": 1, - "tasks": [ - { - "id": 1, - "module": "codelint", - "task_name": "pylint", - "progress_rate": 1, - "state": 2, - "result_code": 0, - "result_msg": "success", - "result_path": null - } - ], - "co_jobs": [], - "state": 2, - "result_code": 0, - "result_code_msg": null, - "result_msg": "success", - "result_path": null, - "remarks": null, - "remarked_by": null, - "code_line_num": 1000, - "comment_line_num": 5, - "blank_line_num": 305, - "total_line_num": 1400, - "created_from": "codedog_web", - "creator": "creator" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - diff --git "a/web/packages/tca-document/en/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" "b/web/packages/tca-document/en/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" deleted file mode 100644 index 434e73de3..000000000 --- "a/web/packages/tca-document/en/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" +++ /dev/null @@ -1,59 +0,0 @@ -# 对象主要字段说明 - -注:以下字段用于参考,具体字段格式需要以具体接口返回为准 - -## 团队(org): -``` -org_sid: str,团队编号 -name: str,团队名称 -description: str,团队描述 -certificated: boolean,团队认证标志位 -created_time: datetime,团队创建时间 -updated_time: datetime,团队更新时间 -admins: list,管理员列表 -project_count: int,分析任务数量 -team_count: int,项目组数量 -user_count: int,成员数量 -owner: str,负责人名称 -tel_number: str,负责人电话 -address: str,办公地址 -``` - -## 项目(team): -``` -name: str,项目组名称 -display_name: str,项目组展示名称 -description: str,项目组描述信息 -``` - -## 代码库(repository): -``` -name: str,代码库名称 -scm_url: str,代码库地址 -scm_type: int,代码库类型 -created_from: str,创建来源 -state:str,代码库状态,1表示活跃,2表示失活,3表示暂停使用 -labels:list,标签 -project_team: 项目 -organization: 团队 -``` - -## 扫描方案(scanscheme): -``` -name: str,扫描方案名称 -repo:关联的代码库 -refer_scheme: 参照的扫描方案 -description: str,描述 -tag: 执行标签 -languages: 包含语言 -default_flag: boolean,默认方案标志 -created_from: str,创建来源 -ignore_merged_issue: boolean,过滤其他分支引入的问题,默认False,不过滤 -ignore_branch_issue: str,过滤指定分支引入的问题 -ignore_submodule_clone: boolean,不拉取子模块,默认False -ignore_submodule_issue: boolean,忽略子模块问题,默认False -issue_global_ignore: boolean,开启问题全局忽略,默认False -daily_save: boolean,日常扫描记录保存7天开关,默认False -lfs_flag: boolean,自动拉取lfs文件,默认True -status: int,扫描方案状态,1为活跃,2为废弃 -``` \ No newline at end of file diff --git "a/web/packages/tca-document/en/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/en/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 089b93059..000000000 --- "a/web/packages/tca-document/en/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,812 +0,0 @@ -# 代码扫描管理 - -## 查看项目扫描最新结果概览 -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/ -``` - -#### 返回结果 -```JSON -{ - "lintscan": { - "issue_open_num": 74, - "issue_fix_num": 439, - "issue_detail_num": 310, - "scan": { - "id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "execute_time": "00:02:17.844712" - }, - "current_scan": { - "active_category_detail": { - "convention": 70, - "other": 4 - }, - "active_severity_detail": { - "error": 69, - "warning": 5 - }, - "issue_open_num": 74, - "issue_fix_num": 439 - }, - "total": { - "state_detail": { - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "category_detail": { - "convention": { - "active": 184, - "resolved": 13, - "closed": 21143 - }, - "other": { - "active": 13, - "closed": 154 - }, - "correctness": { - "closed": 1997 - }, - "performance": { - "closed": 3 - } - }, - "severity_detail": { - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - }, - "status": 0, - "text": "成功", - "description": null, - "scan_summary": { - "convention": { - "error": { - "rule_count": 7, - "active": 65 - }, - "warning": { - "rule_count": 2, - "active": 5 - } - }, - "other": { - "error": { - "rule_count": 1, - "active": 4 - } - } - }, - "total_summary": { - "correctness": { - "error": { - "rule_count": 16, - "closed": 1315 - }, - "warning": { - "rule_count": 10, - "closed": 629 - }, - "info": { - "rule_count": 1, - "closed": 53 - } - }, - "performance": { - "warning": { - "rule_count": 1, - "closed": 3 - } - }, - "convention": { - "error": { - "rule_count": 42, - "active": 149, - "resolved": 11, - "closed": 18778 - }, - "warning": { - "rule_count": 17, - "active": 35, - "resolved": 2, - "closed": 2298 - }, - "info": { - "rule_count": 1, - "closed": 67 - } - }, - "other": { - "error": { - "rule_count": 2, - "active": 8, - "closed": 20 - }, - "warning": { - "rule_count": 1, - "active": 5 - }, - "info": { - "rule_count": 3, - "closed": 134 - } - } - } - }, - "cyclomaticcomplexityscan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "min_ccn": 20, - "over_cc_func_count": 6, - "under_cc_func_count": 796, - "diff_over_cc_func_count": 0, - "over_cc_func_average": 22.333333333333332, - "cc_func_average": 2.5099750623441395, - "over_cc_sum": 14, - "cc_average_of_lines": 1.0422094841063054 - }, - "custom_summary": null, - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", - "diff_cc_num": 0, - "cc_open_num": 6, - "cc_average_of_lines": 1.0422094841063054, - "cc_fix_num": 0, - "worse_cc_file_num": 0, - "min_ccn": 20, - "code_line_num": 13433, - "scan": 1 - }, - "duplicatescan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "exhi_risk": { - "range": [ - 0.2, - 1 - ], - "file_count": 1, - "diff": { - "diff_file_count": 0 - } - }, - "high_risk": { - "range": [ - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { - "range": [ - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { - "range": [ - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, - "last_revision": "last_revision", - "duplicate_file_count": 8, - "duplicate_block_count": 55, - "duplicate_line_count": 1177, - "diff_duplicate_block_count": 0, - "diff_duplicate_line_count": 0, - "close_issue_count": 0, - "new_issue_count": 0, - "reopen_issue_count": 5, - "ignored_issue_count": 0, - "duplicate_rate": 4.98, - "unique_duplicate_line_count": 1083, - "total_duplicate_line_count": 1083, - "total_line_count": 21745, - "scan": 1 - }, - "clocscan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "last_revision": "last_revision", - "code_line_num": 140490, - "comment_line_num": 5410, - "blank_line_num": 3408, - "total_line_num": 149308, - "add_code_line_num": 6673, - "add_comment_line_num": 2309, - "add_blank_line_num": 1289, - "add_total_line_num": 10271, - "mod_code_line_num": 965, - "mod_comment_line_num": 297, - "mod_blank_line_num": 0, - "mod_total_line_num": 1262, - "del_code_line_num": 35844, - "del_comment_line_num": 2117, - "del_blank_line_num": 1794, - "del_total_line_num": 39755, - "scan": 1 - } -} -``` - -## 查看项目代码最新扫描结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/latestscan/ -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_revision | str | 指定查询的扫描版本号,如不指定则为当前项目最新的一次扫描 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, # 扫描编号 - "repo_id": 1, # 代码库编号 - "project_id": 1, # 项目编号 - "job_gid": 1, # 关联任务编号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "current_revision": "current_revision", # 扫描版本号 - "result_code": 0, # 扫描任务结果码,0表示正常 - "result_code_msg": "成功", - "result_msg": null, - "lintscan": { # 代码扫描结果信息 - "current_scan": { # 本次扫描信息 - "active_severity_detail": { # 不同严重级别的活跃问题数,包含 fatal(1-致命), error(2-错误), warning(3-警告), info(4-提示) - "error": 69, - "warning": 5 - }, - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2 # 本次扫描关闭存量问题数 - }, - "total": { # 当前项目整体信息 - "state_detail": { # 不同处理状态的问题数,包含 active(1-活跃)、resolved(2-已处理)、closed(3-已关闭) - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "severity_detail": { # 不同严重级别下不同处理状态的问题量 - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - } - }, - "duplicatescan": { # 重复代码扫描结果信息 - "id": 1, # 扫描任务编号 - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "default_summary": { # 默认概览 - "exhi_risk": { # 极高风险 - "range": [ # 重复率范围: 0.2-1 - 0.2, - 1 - ], - "file_count": 1, # 文件数量 - "diff": { # 增量数据 - "diff_file_count": 0 # 增量文件数量 - } - }, - "high_risk": { # 高风险 - "range": [ # 重复率范围:0.11-0.2 - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { # 中风险 - "range": [ # 重复率范围:0.05-0.11 - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { # 低风险 - "range": [ # 重复率范围:0-0.05 - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, # 自定义概览数据 - "last_revision": "2010ef28ff3a26424d4e8f32df022f90cd682eda", # 上次扫描版本号 - "duplicate_file_count": 8, # 重复文件数量 - "duplicate_block_count": 55, # 重复代码块数量 - "duplicate_line_count": 1177, # 重复代码行数 - "diff_duplicate_block_count": 0, # 增量重复代码块数量 - "diff_duplicate_line_count": 0, # 增量重复代码行数 - "close_issue_count": 0, # 关闭问题数 - "new_issue_count": 0, # 新增问题数 - "reopen_issue_count": 5, # 重新打开问题数 - "ignored_issue_count": 0, # 忽略问题数 - "duplicate_rate": 4.98, # 重复率 - "unique_duplicate_line_count": 1083, # 去重后的重复代码行数 - "total_duplicate_line_count": 1083, # 项目总的去重后的重复代码行数 - "total_line_count": 21745, # 项目总行书 - "scan": 1 # 关联扫描任务编号 - }, - "cyclomaticcomplexityscan": { # 圈复杂度扫描数据 - "id": 1, # 圈复杂度扫描编号 - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { # 默认概览数据 - "min_ccn": 20, # 最小圈复杂度阈值 - "over_cc_func_count": 6, # 超标函数数量 - "under_cc_func_count": 796, # 未超标函数数量 - "diff_over_cc_func_count": 0, # 增量超标函数数据 - "over_cc_func_average": 22.333333333333332, # 平均超标圈复杂度 - "cc_func_average": 2.5099750623441395, # 平均圈复杂度 - "over_cc_sum": 14, # 文件超标方法圈复杂度超过阈值的差值之和 - "cc_average_of_lines": 1.0422094841063054 # 千行代码平均圈复杂度 - }, - "custom_summary": null, # 自定义概览数据 - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", # 上一次扫描版本号 - "diff_cc_num": 0, # 增量超标函数数量 - "cc_open_num": 6, # 超标函数量 - "cc_average_of_lines": 1.0422094841063054, # 千行代码平均圈复杂度 - "cc_fix_num": 0, # 修复数量 - "worse_cc_file_num": 0, # 圈复杂度恶化的文件数据 - "min_ccn": 20, # 最小圈复杂度阈值 - "code_line_num": 13433, # 代码行数 - "scan": 1 - }, - "clocscan": { - "id": 1, - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "last_revision": "last_revision", # 上一次扫描版本号 - "code_line_num": 140490, # 代码行数 - "comment_line_num": 5410, # 注释行数 - "blank_line_num": 3408, # 空白行数 - "total_line_num": 149308, # 总行数 - "add_code_line_num": 6673, # 增加的代码行数 - "add_comment_line_num": 2309, # 增加的注释行数 - "add_blank_line_num": 1289, # 增加的空白行数 - "add_total_line_num": 10271, # 增加的总行数 - "mod_code_line_num": 965, # 修改的代码行数 - "mod_comment_line_num": 297, # 修改的注释行数 - "mod_blank_line_num": 0, # 修改的空白行数 - "mod_total_line_num": 1262, # 修改的总行数 - "del_code_line_num": 35844, # 删除的代码行数 - "del_comment_line_num": 2117, # 删除的注释行数 - "del_blank_line_num": 1794, # 删除的空白行数 - "del_total_line_num": 39755, # 删除的总行数 - "scan": 1 - } - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 查看项目代码扫描结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/lintscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2, # 本次扫描关闭存量问题数 - "issue_detail_num": 310, # 本次扫描上报原始问题数(问题展示会进行聚合) - "scan": { # 扫描信息 - "id": 1, # 扫描任务编号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描开始时间 - "execute_time": "00:02:17.844712" # 扫描执行耗时 - }, - "current_scan": { # 本次扫描信息 - "active_category_detail": { # 活跃问题分类,包含 CORRECTNESS(1-功能)、SECURITY(2-安全)、PERFORMANCE(3-性能)、USABILITY(4-可用性)、ACCESSIBILITY(5-无障碍化)、I18N(6-国际化)、CONVENTION(7-代码风格)、OTHER(8-其他) - "convention": 70, # 代码风格类型问题 - "other": 4 # 其他类型问题 - }, - "active_severity_detail": { # 不同严重级别的活跃问题数,包含 fatal(1-致命), error(2-错误), warning(3-警告), info(4-提示) - "error": 69, - "warning": 5 - }, - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2 # 本次扫描关闭存量问题数 - }, - "total": { # 当前项目整体信息 - "state_detail": { # 不同处理状态的问题数,包含 active(1-活跃)、resolved(2-已处理)、closed(3-已关闭) - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "category_detail": { # 不同分类下不同处理状态的问题量 - "convention": { - "active": 184, - "resolved": 13, - "closed": 21143 - }, - "other": { - "active": 13, - "closed": 154 - }, - "correctness": { - "closed": 1997 - }, - "performance": { - "closed": 3 - } - }, - "severity_detail": { # 不同严重级别下不同处理状态的问题量 - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - }, - "status": 0, # 扫描状态,0表示成功 - "text": "成功", - "description": null, - "scan_summary": { # 扫描概览 - "convention": { - "error": { - "rule_count": 7, # 规则数 - "active": 65 # 活跃问题数 - }, - "warning": { - "rule_count": 2, - "active": 5 - } - }, - "other": { - "error": { - "rule_count": 1, - "active": 4 - } - } - }, - "total_summary": { - "correctness": { - "error": { - "rule_count": 16, - "closed": 1315 - }, - "warning": { - "rule_count": 10, - "closed": 629 - }, - "info": { - "rule_count": 1, - "closed": 53 - } - }, - "performance": { - "warning": { - "rule_count": 1, - "closed": 3 - } - }, - "convention": { - "error": { - "rule_count": 42, - "active": 149, - "resolved": 11, - "closed": 18778 - }, - "warning": { - "rule_count": 17, - "active": 35, - "resolved": 2, - "closed": 2298 - }, - "info": { - "rule_count": 1, - "closed": 67 - } - }, - "other": { - "error": { - "rule_count": 2, - "active": 8, - "closed": 20 - }, - "warning": { - "rule_count": 1, - "active": 5 - }, - "info": { - "rule_count": 3, - "closed": 134 - } - } - } - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量圈复杂度结果概览 -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/cycscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "min_ccn": 20, - "over_cc_func_count": 6, - "under_cc_func_count": 796, - "diff_over_cc_func_count": 0, - "over_cc_func_average": 22.333333333333332, - "cc_func_average": 2.5099750623441395, - "over_cc_sum": 14, - "cc_average_of_lines": 1.0422094841063054 - }, - "custom_summary": null, - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", - "diff_cc_num": 0, - "cc_open_num": 6, - "cc_average_of_lines": 1.0422094841063054, - "cc_fix_num": 0, - "worse_cc_file_num": 0, - "min_ccn": 20, - "code_line_num": 13433, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量重复代码结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/dupscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "exhi_risk": { - "range": [ - 0.2, - 1 - ], - "file_count": 1, - "diff": { - "diff_file_count": 0 - } - }, - "high_risk": { - "range": [ - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { - "range": [ - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { - "range": [ - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, - "last_revision": "last_revision", - "duplicate_file_count": 8, - "duplicate_block_count": 55, - "duplicate_line_count": 1177, - "diff_duplicate_block_count": 0, - "diff_duplicate_line_count": 0, - "close_issue_count": 0, - "new_issue_count": 0, - "reopen_issue_count": 5, - "ignored_issue_count": 0, - "duplicate_rate": 4.98, - "unique_duplicate_line_count": 1083, - "total_duplicate_line_count": 1083, - "total_line_count": 21745, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量代码统计结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/clocscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "last_revision": "last_revision", - "code_line_num": 140490, - "comment_line_num": 5410, - "blank_line_num": 3408, - "total_line_num": 149308, - "add_code_line_num": 6673, - "add_comment_line_num": 2309, - "add_blank_line_num": 1289, - "add_total_line_num": 10271, - "mod_code_line_num": 965, - "mod_comment_line_num": 297, - "mod_blank_line_num": 0, - "mod_total_line_num": 1262, - "del_code_line_num": 35844, - "del_comment_line_num": 2117, - "del_blank_line_num": 1794, - "del_total_line_num": 39755, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - diff --git "a/web/packages/tca-document/en/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/en/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index b18030f49..000000000 --- "a/web/packages/tca-document/en/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,763 +0,0 @@ -# 项目管理模块 - -## 查看指定代码库的指定分支项目列表 - -``` -GET /server/main/api/orgs//teams//repos/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scm_url_or_name | str | 代码库地址或者名称,支持模糊匹配 | -| scm_url | str | 代码库仓库匹配| -| scope | str | 过滤范围(my/subscribed/related_me),my表示我创建的,subscribed表示我关注的,related_me表示我有权限的 | - -#### 返回结果 -```JSON -{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "name": "test_repo.git", - "scm_url": "http://git.com/xxx/test_repo", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-03-15 02:26:31.423674+00:00", - "recent_active": { - "id": 1, - "branch_name": "master", - "active_time": "2021-03-15T03:14:56.760427Z", - "total_line_num": null, - "code_line_num": null - }, - "created_from": "codedog_web", - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "symbol": null - } - ] -} -``` - -## 查看指定代码库详情 - -``` -GET /server/main/api/orgs//teams//repos// -``` - -#### 返回结果 -```JSON -{ - "data":{ - "id": 1, - "name": "test_repo.git", - "scm_url": "http://git.com/xxx/test_repo", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-03-15 02:26:31.423674+00:00", - "recent_active": { - "id": 1, - "branch_name": "master", - "active_time": "2021-03-15T03:14:56.760427Z", - "total_line_num": null, - "code_line_num": null - }, - "created_from": "codedog_web", - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "symbol": null - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 查看指定代码库的不同分支的列表接口 - -``` -GET /server/main/api/orgs//teams//repos//branches/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "branch": "master", - "schemes": [ - { - "project_id": 1, - "scan_scheme_id": 1, - "scan_scheme_name": "默认" - } - ] - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的分支项目列表 - -``` -GET /server/main/api/orgs//teams//repos//projects/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| branch | str | 分支名称 | -| scan_scheme | int | 扫描方案名称 | -| scan_scheme__status | int | 扫描方案状态,1为活跃,2为废弃 | -| branch_or_scheme | str | 分支名称/扫描方案名称 | -| status | int | 项目状态筛选,1表示活跃,2表示失活,3表示关闭 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "codedog_web", - "repo": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 创建指定代码库的指定分支项目 - -``` -POST /server/main/api/orgs//teams//repos//projects/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_scheme_id | int | 当前代码库的扫描方案编号 | -| global_scheme_id | int | 扫描方案模板编号 | -| custom_scheme_name | str | 自定义方案名称 | -| branch | str | 分支 | -| created_from | str | 创建渠道,用于区分不同运行场景 | - -#### 返回结果 -```JSON -{ - "data": { - "id":1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "repo": { - "id": 1, - "name": "test_demo.git", - "scm_url": "http://github.com/xxxx/test_demo.git", - "scm_type": "git", - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "1", - "scm_platform": 1, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - } - }, - "auth_type": "ssh_token", - "created_time": "2021-01-28T10:26:31.453389+08:00", - "modified_time": "2021-01-28T10:26:31.453417+08:00" - }, - "symbol": null - }, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "tca_web" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的指定分支项目 - -``` -GET /server/main/api/orgs//teams//repos/// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id":1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "repo": { - "id": 1, - "name": "test_demo.git", - "scm_url": "http://github.com/xxxx/test_demo.git", - "scm_type": "git", - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "1", - "scm_platform": 1, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - } - }, - "auth_type": "ssh_token", - "created_time": "2021-01-28T10:26:31.453389+08:00", - "modified_time": "2021-01-28T10:26:31.453417+08:00" - }, - "symbol": null - }, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "tca_web" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的扫描方案列表 -``` -GET /server/main/api/orgs//teams//repos//schemes/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| name | str | 扫描方案名称 | -| status | int | 扫描方案状态,1为活跃,2为废弃 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "issue_revision_merge_flag": false, - "status": 1, - "repo": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的指定扫描方案 -``` -GET /server/main/api/orgs//teams//repos//schemes//basicconf/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "issue_revision_merge_flag": false, - "status": 1, - "repo": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 更新指定代码库的指定方案 -``` -PUT /server/main/api/orgs//teams//repos//schemes//basicconf/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| languages | list | 代码语言 | -| tag | str | 执行标签,目前只支持 CodeDog_Linux | -| name | str | 方案名称 | -| description | str | 方案描述 | -| default_flag | bool | 默认方案标志,一个代码库只能有一个默认方案 | -| job_runtime_limit | int | 任务执行超时时间,默认为600分钟 | -| ignore_merged_issue | bool | 忽略合入的问题 | -| ignore_branch_issue | str | 过滤参考分支引入的问题 | -| ignore_submodule_clone | bool | 不拉取子模块扫描,True表示不拉取,False表示拉取 | -| ignore_submodule_issue | bool | 忽略子模块引入的问题,True表示忽略,False表示不忽略 | -| issue_global_ignore | bool | 问题全局忽略 | -| daily_save | bool | 每次扫描原始数据存储,默认存储7天 | -| lfs_flag | bool | 拉取lfs模块开关 | -| issue_revision_merge_flag | bool | "是否开启Issue按引入版本号聚合开关 | -| status | int | 方案状态,1表示活跃,2表示废弃| - -#### 返回结果 -同[查看指定代码库的指定扫描方案](查看指定代码库的指定扫描方案)的返回结果一致 - - -## 查看指定代码库的扫描方案的代码扫描配置 -``` -GET /server/main/api/orgs//teams//repos//schemes//lintconf/ -``` -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "enabled": true, - "checkprofile": { - "id": 1, - "profile_type": 1, - "custom_checkpackage": 1, - "checkpackages": [ - 1 - ] - }, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 更新指定代码库的指定方案的代码扫描配置 -``` -PUT /server/main/api/orgs//teams//repos//schemes//lintconf/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| enabled | bool | 是否开启代码扫描 | - -#### 返回结果 -同[指定代码库的指定方案的代码扫描配置](指定代码库的指定方案的代码扫描配置)的返回结果一致 - -## 查看指定代码库的扫描方案的代码度量配置 -``` -GET /server/main/api/orgs//teams//repos//schemes//metricconf/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "cc_scan_enabled": false, - "min_ccn": 20, - "dup_scan_enabled": false, - "dup_block_length_min": 120, - "dup_block_length_max": null, - "dup_min_dup_times": 2, - "dup_max_dup_times": null, - "dup_min_midd_rate": 5, - "dup_min_high_rate": 11, - "dup_min_exhi_rate": 20, - "dup_issue_limit": 1000, - "cloc_scan_enabled": false, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 更新指定代码库的指定方案的代码度量配置 -``` -PUT /server/main/api/orgs//teams//repos//schemes//metricconf/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| cc_scan_enabled | bool | 圈复杂度扫描开关 | -| min_ccn | int | 最小圈复杂度 | -| dup_scan_enabled | bool | 重复代码扫描开关 | -| dup_block_length_min | int | 重复块最小长度 | -| dup_block_length_max | int | 重复块最大长度 | -| dup_max_dup_times | int | 最大重复次数 | -| dup_min_midd_rate | int | 中风险最小重复率 | -| dup_min_high_rate | int | 高风险最小重复率 | -| dup_min_exhi_rate | int | 极高风险风险最小重复率 | -| dup_issue_limit | int | 上报重复代码块数上限 | -| cloc_scan_enabled | boolean | 代码统计扫描开关 | - -#### 返回结果 -同[指定代码库的指定方案的代码度量配置](指定代码库的指定方案的代码度量配置)的返回结果一致 - -## 查看指定代码库的扫描方案的过滤路径列表 -``` -GET /server/main/api/orgs//teams//repos//schemes//scandirs/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "dir_path": "test/*", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 创建指定代码库的指定方案的过滤路径列表 -``` -POST /server/main/api/orgs//teams//repos//schemes//scandirs/ -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| dir_path |str | 指定过滤路径 | -| path_type | int | 路径格式,1表示通配符,2表示正则表达式,默认为通配符 | -| scan_type | int | 扫描类型,1表示包含,2表示排除 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 13, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 36 - }, - "code": 0, - "msg": "请求成功", - "status_code": 201 -} -``` - - -## 查看指定代码库的扫描方案的指定过滤路径 -``` -GET /server/main/api/orgs//teams//repos//schemes//scandirs// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 更新指定代码库的指定方案的指定过滤路径 -``` -PUT /server/main/api/orgs//teams//repos//schemes//scandirs// -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| dir_path |str | 指定过滤路径 | -| path_type | int | 路径格式,1表示通配符,2表示正则表达式,默认为通配符 | -| scan_type | int | 扫描类型,1表示包含,2表示排除 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 13, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 36 - }, - "code": 0, - "msg": "请求成功", - "status_code": 201 -} -``` - -## 删除指定代码库的指定方案的指定过滤路径 -``` -DELETE /server/main/api/orgs//teams//repos//schemes//scandirs// -``` - -#### 返回结果 -无 diff --git a/web/packages/tca-document/en/community/changelog.md b/web/packages/tca-document/en/community/changelog.md deleted file mode 100644 index e3fd99512..000000000 --- a/web/packages/tca-document/en/community/changelog.md +++ /dev/null @@ -1,106 +0,0 @@ -# 更新日志 - -## V1.2.0 (2022-4-27) - -### Features - -- 【Web端】增加工具管理 -- 【工具】增加logback检查的安全规则 -- 【服务端】增加TCA server&web 一键部署脚本 -- 【服务端】删除main部分异步任务;调整server nginx启动位置 -- 【服务端】增加server健康监测 - -### Docs - -- 完善部署和Q&A文档 -- 上传工具列表 - -## V1.1.3 (2022-4-18) - -### Features - -- 【工具】上传开源合规检查规则 -- 【工具】新增PHP安全相关规则 -- 【服务端】上线license鉴权 -- 【客户端】支持对工具license校验 - -### Docs - -- 更新文档内的工具默认路径 -- 增加任务分布式执行能力操作文档 -- 增加PR操作流程 - -## V1.1.2 (2022-4-2) - -### Features - -- 【服务端】优化部署构建脚本 - -### Docs - -- 简化前端部署脚本&文档 -- 优化指引文档 - -## V1.1.1 (2022-3-31) - -### Features - -- 【工具】增加0daychecker工具 -- 【工具】增加Log4j、LogBack漏洞检查规则包 - -### Docs - -- 完善部署文档说明,推荐使用Docker-Compose 2.3.3版本 - -## V1.1.0 (2022-3-29) - -### Features - -- 【客户端】client支持arm64架构执行环境 -- 【客户端】client新增分布式节点模式 -- 【客户端】修改参数isTotal(是否开启全量扫描)判断方式及参数startCommand(启动客户端命令)拼接方式 -- 【服务端】支持任务分布式下发 -- 【服务端】完善基于minio的文件存储配置 -- 【Web端】调整文件资源引用地址 -- 【Web端】web模块部署脚本问题修复及优化 -- 【Web端】增加管理后台、增加在线分析 -- 【Web端】调整前端部署脚本,支持传递nginx配置地址、前端资源部署地址 - -### Bugfixes - -- Jenkins插件命令拼装逻辑修正 - -### Docs - -- 调整pypi下载失败提示 -- 调整前端部署文档及脚本 -- 更新License - -## V1.0.1 (2022-03-01) - -### Features - -- feat: 【服务端】调整代码库登记ssh url链接格式适配 -- feat: 【工具】上线支持PHP安全工具-Rips -- feat: 【工具】调整androidlint部分规则描述 -- feat: 【客户端】上线Jenkins插件 -- feat: 【客户端】增加工具拉取可选配置项 -- feat: 【客户端】支持在命令行参数中输入团队编号和项目名称 -- feat: 【客户端】限制PYTHON_VERSION环境变量可选值 -- feat: 【客户端】增加在docker中快速使用client的方式 - -### Bugfixes - -- fix: 【服务端】补充缺失的依赖 -- fix: 【Web端】修复下载codedog.ini失败提示 - -### Docs - -- doc: 上线部署文档Q&A -- doc: 优化部署文档、帮助文档说明 -- doc: 增加产品白皮书 -- doc: 补充redis和nginx源码安装参考文档 - -## V1.0.0 - -初始发布 diff --git a/web/packages/tca-document/en/community/contribute.md b/web/packages/tca-document/en/community/contribute.md deleted file mode 100644 index 62e870ba1..000000000 --- a/web/packages/tca-document/en/community/contribute.md +++ /dev/null @@ -1,46 +0,0 @@ -# 贡献指南 - -欢迎报告Issue或提交Pull Request。建议在贡献代码前先阅读以下贡献指南。 - -## 报告问题 - -我们使用[Github Issues](https://github.com/Tencent/CodeAnalysis/issues)来跟踪漏洞和功能请求。 - -### 搜索已知issue - -在您提交新的issue前,请搜索现有issue以查看是否已有人提交任何类似问题或功能请求,确认不存在重复的issue。 - -### 报告新issue - -当您提交新的issue时,请尽量提供更多的信息,例如与问题相关的详细描述、屏幕截图、视频、logcat和导致崩溃的代码块。 - -## Pull Request - -我们非常欢迎您提出Pull Request来帮助TCA变得更好,操作流程详见[PullRequests操作流程](./pr.md)。 - -### 分支管理 - -TCA有两个主要分支: - -- `main` 分支: - 1. 它是最新的(预)发布分支。我们以 `main` 作为标签, 带有版本号 `v1.0.1`, `v1.0.2` ... - 2. **请不要在 `main` 分支提交任何PR.** -- `dev` 分支: - 1. 这是我们稳定发展的分支。经过全面测试后, `dev` 分支将合并到 `main` 分支的下一个版本。 - 2. **请您将修复漏洞或开发新功能的PR提交到 `dev` 分支。** - -### 提交Pull Request - -代码团队将监控所有拉取请求,我们对其进行一些代码检查和测试。在所有测试通过后,我们将接受此PR。但它不会立即合并到 `main` 分支,这有一些延迟。 - -在提交拉取请求之前,请确保完成以下工作: - -1. Fork [TCA仓库](https://github.com/Tencent/CodeAnalysis/blob/main/CONTRIBUTING.md),并从 `main` 创建分支。 -2. 如果您更改了API,请更新代码或文档。 -3. 将版权声明添加到您添加的任何新文件的顶部。 -4. 检查您的代码样式。 -5. 测试您的代码,确保其可以正常运行。 -6. 现在,您可以向 `dev` 分支提交Pull Request。 - -## 许可 -[MIT LICENSE](https://github.com/Tencent/CodeAnalysis/blob/main/LICENSE) 是 TCA 的开源许可证。任何人贡献的代码都受此许可证保护。在贡献代码之前,请确保您可以接受许可。 \ No newline at end of file diff --git a/web/packages/tca-document/en/community/joingroup.md b/web/packages/tca-document/en/community/joingroup.md deleted file mode 100644 index 1b3c25b08..000000000 --- a/web/packages/tca-document/en/community/joingroup.md +++ /dev/null @@ -1,7 +0,0 @@ -# 加入社区 - -如果您需要有关TCA的帮助,希望与TCA开发者们相互认识和交流,欢迎通过以下渠道加入TCA社区! - -- 微信公众号:「腾讯云静态分析」,关注并发送“进群”即可加入官方开源交流微信群 -- QQ交流群:361791391 -- [GitHub讨论区](https://github.com/Tencent/CodeAnalysis/discussions) \ No newline at end of file diff --git a/web/packages/tca-document/en/community/pr.md b/web/packages/tca-document/en/community/pr.md deleted file mode 100644 index 1c0fc8852..000000000 --- a/web/packages/tca-document/en/community/pr.md +++ /dev/null @@ -1,51 +0,0 @@ -![Welcome](../../images/Welcome.png) - -PR全称为Pull Request,它是一种代码库的协作方式。开发者可以通过PR将自己在代码库的修改通知到代码库负责人,由原作者评审代码并决定是否能合入。 - -:::tip -Pull requests let you tell others about changes you've pushed to a branch in a repository on GitHub. Once a pull request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits before your changes are merged into the base branch. -::: - -# PR操作流程 - -## 一、Fork目标代码库 - -![fork](../../images/Fork.png) - -点击Fork后,会在自己名下产生一个相同代码库,比如我Fork CodeAnalysis项目后,会在我名下多出一个CodeAnalysis代码库,地址为 - -## 二、克隆Fork的代码库并创建分支 - -在本地克隆Fork的代码库并创建分支 - -```bash -git clone https://github.com/Lingghh/CodeAnalysis -git checkout -b dev/add_qa_20220301 -``` - - 注:也可以在自己Fork的代码库GitHub页面上创建分支。 - - ![fork1](../../images/fork1.png) - - 接下来就可以在本地修改代码,修改完成后先push到Fork的代码库中. - -## 三、在目标项目中提交PR - -### 1.进入到目标项目中,点击Pull requests Tab,再点击New pull request就会进入到创建PR的页面 - -![New pull request](../../images/NewPullRequest.png) - -### 2.进入PR页面后 - -- 点击compare across forks 。 -- 点击head repository 。 -- 选择自己Fork的代码库和比较的分支,比如我这里选择Lingghh/CodeAnalysis和待合入的分支dev/add_arm64_file 。 -- 最后确认commits和changed files是否准确,如果没有问题就可以点击Create pull request 。 - - ![PR](../../images/PR.png) - -PR创建后,代码库管理员会评审你提交的代码,并决定是否接受该PR。 - -## 更多信息请参阅[GitHub PullRequest官方文档](https://docs.github.com/cn/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests/) - -## TCA团队诚邀您的加入 diff --git a/web/packages/tca-document/en/guide/README.md b/web/packages/tca-document/en/guide/README.md deleted file mode 100644 index 7c9c9ea9e..000000000 --- a/web/packages/tca-document/en/guide/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# 腾讯云代码分析 - -**腾讯云代码分析**(**Code Analysis, TCA**)起步于 2012 年(内部代号CodeDog),是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。 - -用心关注每行代码迭代、助力传承卓越代码文化! - -精准跟踪管理代码分析发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码,以及度量代码复杂度、重复代码、代码统计。 - -代码分析是通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行分析,验证代码是否满足**规范性**、**安全性**、**可靠性**、**可维护性**、**部分性能**等,对代码进行综合分析和度量等指标的一种代码分析技术。 - -## 主要功能 - -### 代码检查 - -通过代码检查精准跟踪管理发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码等。 - -目前已集成众多自研、知名开源分析工具,并采用了分层分离架构,可以满足团队快速自助管理工具。 - -### 代码度量 - -包含代码圈复杂度、代码重复率和代码统计等度量信息。 - -#### 代码圈复杂度 - -圈复杂度也称为条件复杂度或循环复杂度,它可以用来衡量一个模块判定结构的复杂程度。圈复杂度大说明程序代码的判断逻辑复杂,可能造成代码质量低下且难于测试和维护。 - -定期分析工程项目中代码的圈复杂度,可以有效地帮助开发与测试逐步优化代码质量。 - -#### 代码重复率 - -定期分析工程项目中的重复代码,可以有效地帮助开发发现冗余代码,进行代码抽象和重构,降低代码风险,以便于更好的管理和维护代码。 - -#### 代码统计 - -支持全量增量展示代码行数统计,包含代码行、注释行和空白行,可以有效地跟踪了解工程项目中代码量持续变化,并可以查看各个语言的占比情况。 diff --git a/web/packages/tca-document/en/guide/web/deploySource.md b/web/packages/tca-document/en/guide/web/deploySource.md deleted file mode 100644 index a171c258c..000000000 --- a/web/packages/tca-document/en/guide/web/deploySource.md +++ /dev/null @@ -1,28 +0,0 @@ -# VM 部署文档 - -## 前置条件 - -1. Linux 环境 - -2. 系统已安装 nginx - -3. TCA Server 服务已部署完毕,具备后端服务地址 - -## 部署步骤 - -1. **进入前端部署源码目录** - - 进入web服务目录,并切换至`tca-deploy-source`目录,将其视为工作目录(假设工作目录为 `/data/CodeAnalysis/web/tca-deploy-source`) - -2. **部署/更新前端服务** - - ```bash - # 部署、更新都使用此命令 - sh ./scripts/deploy.sh init -d - ``` - - 具体请查阅部署脚本内容,可根据业务调整配置。 - -3. **额外说明** - - `tca-deploy-source/scripts/config.sh` 已配置默认环境变量,用户可根据需要调整环境变量再部署前端服务,具体可查阅脚本内容。 diff --git a/web/packages/tca-document/en/guide/web/web.md b/web/packages/tca-document/en/guide/web/web.md deleted file mode 100644 index 6cdd73816..000000000 --- a/web/packages/tca-document/en/guide/web/web.md +++ /dev/null @@ -1,65 +0,0 @@ -# TCA Web - -## 工程结构 - -TCA Web 采用 [Lerna](https://www.lernajs.cn/) 进行 `monorepo` 管理。 - -:::tip -[Lerna GitHub地址](https://github.com/lerna/lerna) - -[Lerna 中文命令文档](http://www.febeacon.com/lerna-docs-zh-cn/) -::: - -由 `framework`、`login`、`tca-layout`、`tca-analysis`、`tca-manage`微前端以及`tca-document`前端帮助文档组成。 - -### packages 目录说明 - -- `shared`: 公共模块 - -- `framework`: 微前端基座 - -- `login`: 登录微前端 - -- `tca-layout`: 腾讯云代码分析layout微前端 - -- `tca-analysis`: 腾讯云代码分析analysis微前端 - -- `tca-manage`: 腾讯云代码分析后台管理微前端 - -- `tca-document`: 腾讯云代码分析帮助文档 - -## 基于构建后资源部署(tca-deploy-source) - -已将当前版本各个微前端构建打包到此目录,可通过阅读该目录下的 **README** 直接进行前端部署。 - -## 基于开发模式启动 - -- 按上一节完成一套 **TCA Web** 部署 - -- 根据要调整的内容,启动对应的微前端(login、tca-layout、tca-analysis),具体可进入不同 `package` 参考阅读其目录下的 `README` 进行开发。 - -**其他**: - -- **根目录下启动单个项目** - - ```bash - # framework - yarn dev --scope framework - # login - PUBLIC_PATH=http://127.0.0.1:5055/ yarn dev --scope login - # tca-layout - PUBLIC_PATH=http://127.0.0.1:5056/ yarn dev --scope tca-layout - # tca-analysis - PUBLIC_PATH=http://127.0.0.1:5057/ yarn dev --scope tca-analysis - # tca-manage - PUBLIC_PATH=http://127.0.0.1:5058/ yarn dev --scope tca-manage - # tca-document - yarn dev --scope tca-document - # 或进入对应项目内,查阅对应README - ``` - -## 本地开发后构建部署 - -- 如对项目进行变更,本地开发结束后,需要部署最新资源可通过执行 `sh build-source.sh` 将构建后资源更新到**tca-deploy-source** 目录内,再参考该目录下的 **README** 直接进行前端更新/重新部署操作。 - -- 可通过阅读 `build-source.sh` 内容,以及 **tca-deploy-source** 目录下的 **README**,用户可根据需要自行进行前端部署。 diff --git "a/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" "b/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" deleted file mode 100644 index 591f45c64..000000000 --- "a/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" +++ /dev/null @@ -1,31 +0,0 @@ -# 代码检查结果查看 - -客户端分析完毕后,如果分析方案含有代码检查功能,则代码分析结束后会上报结果信息到腾讯云代码分析平台,用户可在平台上查看问题列表及详情。 - -![问题列表](../../../images/codelint_01.png) - -## 问题列表 - -进入代码检查问题列表页面后,默认展示**当前分支 + 当前分析方案(即分支项目)**发现的全部未处理问题。 - -如果仅希望查看增量问题,可以进入分析历史页面,指定查看某一次的扫描结果即可。也可以在过滤筛选项中填入发现问题的扫描 `id`进行筛选查看结果(该`id`为扫描任务 ID,需要到扫描任务列表中查询)。 - -- **责任人说明** - - 责任人为 `git blame`操作得到的代码提交人。 - -- **问题级别说明** - - 代码检查的问题级别是根据对应分析方案中规则设置的严重级别定义的,从高到低分为 **`致命、错误、警告、提示`** 。如果调整问题级别,则需要进入分析方案中调整这个规则的严重级别,调整后需要进行全量扫描使得调整生效。 - -- **批量处理说明** - - 问题列表支持批量修改问题状态。 - - ![批量处理](../../../images/codelint_02.png) - -## 问题详情 - -点击规则信息可以查看规则说明。 - -![查看规则详情](../../../images/codelint_03.png) diff --git "a/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" deleted file mode 100644 index 373c605e5..000000000 --- "a/web/packages/tca-document/en/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 添加规则配置 - -规则配置是代码检查应用的规则集合,用于指定用哪些工具和规则进行代码分析扫描。目前,TCA 提供了覆盖**代码规范**、**安全扫描**、**风格检查**等方面的官方推荐规则包。 - -**官方推荐规则包**是TCA长期以来在业务中实践的经验结果,将相关的有效性高的工具和规则打包在一起。业务可以根据需要选择官方推荐规则包。也可以在自定义规则包中添加希望的工具和规则。 - -::: tip -规则配置 = 自定义规则包 + 官方规则包 - -自定义规则包中的规则配置会默认覆盖其他官方包中相同规则的配置 -::: - - ![添加规则配置](../../../images/AddRule.png) - - 可以单选或者批量多选规则 - ![添加规则配置](../../../images/AddRule2.png) - -也可以根据搜索框进行多维度查询 - ![添加规则配置](../../../images/AddRule3.png) diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" deleted file mode 100644 index 37e2f3706..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" +++ /dev/null @@ -1,31 +0,0 @@ -# 代码度量配置 - -## 圈复杂度 - -可以发现执行路径较多的方法,降低代码的圈复杂度,可测性更高 - -- **检测阈值** - - 默认为 20,表示当一个方法的圈复杂度超过 20 时则认为该方法为超标方法,需要被关注修改。 - - 可以根据需要调整 - -## 重复代码 - -可以发现重复的代码,避免重复代码可以让代码更简洁,更易维护 - -- **长度区间** - - 是一个区间值,默认代码中一个单词(变量/操作符)长度为 1。 - -- **重复次数** - - 是一个区间值,当一段代码重复次数达到指定区间才认为是有风险的。 - -- **上报限制** - - 限制上报的重复代码块数,可以减少开发的压力,提高修复积极性。 - -## 代码统计 - -从目录和业务纬度统计代码行数,也可以获取提交记录便于代码 Review diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" deleted file mode 100644 index 84ecfd8c1..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" +++ /dev/null @@ -1,123 +0,0 @@ -# 代码检查-编译配置 - -腾讯云代码分析平台支持给编译类的工具或编译型项目配置相关命令。 - -由于对代码进行编译型分析会存在安全风险,需要用户自行进行专机扫描,申购完成后可联系平台管理员进行相关配置。 - -::: tip -对于编译型语言,有些分析工具是可以通过分析编译产出的中间文件,更为准确地发现代码质量问题。 -::: - ---- - -::: warning -由于对代码进行编译型分析会存在安全风险,需要用户自行进行专机扫描(私有化版由客户自行评估即可)。 -::: - ---- - -## 编译所需环境说明(重要) - -如果配置了编译命令,则需要在具有代码执行所需的编译环境的节点上执行代码分析。即需要用户在专机上提供编译环境(针对私有化版,客户可根据业务情况选择在公共节点机、用户专机、本地节点机提供编译环境即可)。 - -如以下一些编译环境: - -- JDK 环境及版本 - -- gradle 环境 - -- cmake & make 环境 - -- visual studio 环境 - -- ... - -::: warning -如果机器有多个 JDK 或者 gradle 环境,项目编译需指定 JDK 或 gradle 版本,可以在分析方案的基础属性当中设定相应环境变量。 -::: - -## 编译配置字段说明 - -**前置命令**: - -通常是项目编译前需要执行的命令,或用于清理之前编译过程的命令,如:`make clean`, `xcodebuild clean [-optionName]`。如无需要,可以不填。 - -**编译命令**: - -项目的编译命令,具体可以**咨询该代码库所属项目的开发** - -能够使项目编译成功的编译命令,可以填写多行或用 && 连接命令。 - -::: tip -前置命令与编译命令是隔离的,即在前置命令中的操作不会对编译命令产生影响。 - -如在前置命令中 `cd src && export TEST=src`,在执行编译命令时并不会跳到`src`目录和获取`TEST`环境变量。 -::: - -## 编译配置示例 - -::: tip -咨询该代码库所属项目的开发,先确保先在本地工程根目录调试通过 -::: - -### JAVA 项目 - -**编译命令**: - -android-studio 项目编译命令示例 - -```java -gradle compileDebugSources --no-daemon -Dorg.gradle.jvmargs= -``` - -ant 项目编译命令示例 - -```java -ant build -``` - -### Object-C 项目 - -**编译命令**: - -xcodebuild 命令(确保先在本地工程根目录调试通过) - -```objectivec -xcodebuild -target dailybuildipa -configuration DailyBuild -sdk iphonesimulator -``` - -**环境变量**(分析方案-基础属性中配置): - -```bash -XCODE_VERISON=10.1 -``` - -### C/C++ 项目 - -**编译命令**: - -VS 项目编译命令示例 - -```cpp -devenv.com demo.sln /Build "Debug|Win32" -# 或 -msbuild demo.sln /t:Build /p:Configuration=DebugCopy -``` - -make 项目编译命令示例 - -```cpp -make all -``` - -### C# 项目 - -**编译命令**: - -VS 项目编译命令示例 - -```cs -devenv.com demo.sln /Build "Debug|Win32" -# 或 -msbuild demo.sln /t:Build /p:Configuration=Debug -``` diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" deleted file mode 100644 index 3dd4cf6ba..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 代码检查-规则配置 - -在上一节文档**代码检查配置**中我们大致已经了解规则配置主要由**官方规则包**和**自定义规则包**构成,本节将详细描述规则配置。 - -**官方规则包**是由腾讯云代码分析平台经过多年深耕,在业务中不断实践整理而出的规则集合包,然而平台有超过**10000+**的规则,有些规则并未放到官方规则包中,甚至有些规则是由用户自定义的规则。此外,有些官方规则包中的规则,对于不同的团队所需可能存在差异,因此产生了如下几种问题: - -- **在规则配置中,如何添加规则?** - -- **在规则配置中,如果将官方规则包中的规则进行调整?** - -## 在规则配置中,如何添加规则? - -添加规则存在**两种入口**: - -::: tip -无论何种,最终都是将规则添加到自定义规则包中 -::: - -- 用户可直接点击页面中的添加规则 - - ![添加规则配置](../../../images/AddRule.png) - -- 用户可点击自定义规则,进入自定义规则包后,再点击添加规则 - - ![点击自定义规则包](../../../images/scheme_codelint_02.png) - - ![添加规则](../../../images/scheme_codelint_03.png) - -在添加规则过程中,可以单选或者批量多选规则,可以根据搜索栏进行多维度查询规则 - -![添加规则配置](../../../images/AddRule2.png) - -![添加规则配置](../../../images/AddRule3.png) - -## 在规则配置中,如果将官方规则包中的规则进行调整? - -用户可以点击进入官方规则包,进入官方规则包中,对已存在的规则进行编辑。 - -::: warning -在官方规则包中对规则的任意操作,实质上是将对应规则增加到自定义规则包中进行了相关操作。 - -自定义规则包中的规则配置会默认覆盖其他官方包中相同规则的配置。 -::: - -![编辑官方规则包规则](../../../images/scheme_codelint_04.png) diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" deleted file mode 100644 index 4be078e21..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 代码检查配置 - -腾讯云代码分析采用业界/自研的 80+ 款工具,配置代码检查项能够有效地发现代码中存在的异味代码 - -## 规则配置 - -规则配置主要是以规则包为元素,由**官方规则包**和**自定义规则包**两部分组成。平台提供一些系列的官方规则包,覆盖规范、安全、推荐等方面。 - -用户可根据项目语言、规则包类型筛选不同的规则包,并启用/关闭规则包。 - -::: tip -用户可以根据需要选择官方规则包进行扫描,并可以在官方规则包的基础上屏蔽某些规则或者调整默认的优先级,设置指定参数。这些操作都会记录在自定义规则包中。 - -自定义规则包是提供给用户自由选择工具规则的包。官方规则包上的调整实质上会记录到自定义规则包中,当自定义规则包中的规则和官方规则包的规则发生冲突,则自定义规则包优先级更高。 -::: - -![创建项目](../../../images/scheme_codelint_01.png) - -## 编译配置 - -通过编译(代码解析和翻译过程)分析中间代码进行辅助分析,能更精准地发现更多潜在的代码问题。 diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" deleted file mode 100644 index ffb2d0958..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" +++ /dev/null @@ -1,27 +0,0 @@ -# 分析方案模版 - -为便于用户快速创建代码库进行分析,复用同类型的分析配置,平台提供了分析方案模板功能。 - -分析方案模板分为**系统方案模板**和**个人自定义方案模板**。 - -- **系统方案模板** - - **全局可用**。但是用户无法变更系统方案模板内容。如系统方案模板产生变更,需用户自行拉取最新模板内容。 - - ![同步分析方案模板配置](../../../images/scheme_template_01.png) - -- **个人自定义方案模板** - - 自定义方案模板与团队挂钩,用户可自行创建、更新、同步方案模板,以及可进行权限控制。默认自定义方案模板团队内都可见。 - - ![自定义方案模板权限管理](../../../images/scheme_template_02.png) - -分析方案模版用于在创建分析方案时作为模版参考。分析方案模版全局可用,不用和某个代码库关联。 - -## 使用说明 - -- 创建分支项目时,可选择使用分析方案模板创建。默认会根据该分析方案模板创建出一个新的分析方案,并用该方案配置进行分支项目创建。 - -- 创建分析方案时,可选择使用分析方案模板创建。 - -- 用模版生成的分析方案和模版建立关联关系,当模版和生成的方案由差异时,可以由用户选择是否同步模版的内容到方案。并可以选择拉群哪些功能模块的配置。 diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" deleted file mode 100644 index 3c28a4c40..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 基础属性配置 - -- **方案名称** - - 用于标示一个方案,每个方案名称都是唯一的。 - -- **分析语言** - - 用于指明该方案是针对代码库何种语言进行分析。初次创建分析方案时会根据语言初始化分析方案相关配置。 - -- **运行环境** - - - 对于客户端分析,根据客户端所在本地执行机器选择对应运行环境即可。 - - - 对于在线分析,根据项目实际情况,选取对应运行环境即可。 - - ::: tip - 在线分析时,会根据方案的运行环境,将任务分配到对应环境的节点机器上执行代码分析。 - - 需考虑项目在对应环境的节点机器上能否正常执行 - ::: - -- **环境变量** - - 每行 key-value 形式,非必填项。 - - - **可用于指定特殊编译环境**:如机器有多个 JDK 或者 gradle 环境,项目编译需指定 JDK 或 gradle 版本的可以设定相应环境变量。 - - - **可用于工具传递参数**: 如`ESLINT_MAX_OLD_SPACE_SIZE=4096`配置 Js 内存大小 - - - **可用于指定项目配置**,如`PYTHON_VERSION=2` 指定为 python2 项目 - - ::: tip - 对 Python 的分析默认采用 Python3,如果需要分析 Python2 请在环境变量中设置:PYTHON_VERSION=2 - ::: diff --git "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" "b/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" deleted file mode 100644 index a1548ffbc..000000000 --- "a/web/packages/tca-document/en/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" +++ /dev/null @@ -1,67 +0,0 @@ -# 过滤配置 - -## 路径过滤 - -用于设定代码分析的范围,设定后,已经开启的代码检查、代码度量各项功能都会在指定的代码范围内生效。 - -目前支持**正则表达式**和**通配符**两种类型: - -- **正则表达式** - - ```txt - 请填写相对路径(基于代码库根目录),要求匹配到文件 - 使用正则表达式格式,示例如下: - 代码根目录 - |-src - |- test - |- main_test.py - |- input_test.py - |- main.py - |-test - |- param_test.py - 匹配src/test目录:src/test/.* - 匹配根目录下的test目录:test/.* - 匹配所有_test.py后缀的文件:.*_test\\.py - 修改后,下次分析生效,需要启动一次全量分析处理历史存量问题。 - ``` - - ```txt - Include 表示只分析,如只分析 src/ 目录:src/.* - Exclude 表示只屏蔽,如要屏蔽 src/lib/ 目录:src/lib/.* - ``` - -- **通配符** - - ```txt - 请填写相对路径(基于代码库根目录),要求匹配到文件 - 使用Unix通配符格式,示例如下 - 代码根目录 - |-src - |- test - |- main_test.py - |- input_test.py - |- main.py - |-test - |- param_test.py - 匹配src/test目录:src/test/* - 匹配根目录下的test目录:test/* - 匹配所有_test.py后缀的文件:*_test.py - 修改后,下次分析生效,需要启动一次全量分析处理历史存量问题。 - ``` - - ```txt - Include 表示只分析,如只分析 src/ 目录:src/* - Exclude 表示只屏蔽,如要屏蔽 src/lib/ 目录:src/lib/* - ``` - -如果几个分析方案希望共享相同的路径过滤方案,可以通过导入导出路径配置的方式进行处理。 - -::: tip -配置更改后,下次启动分析生效 -::: - -## 问题过滤 - -- **全局 Issue 忽略状态同步** - - 仅对代码检查生效。开启后,在 Issue 页面进行全局忽略操作时,其他利用该方案分析的分支项目在发现相同 Issue 时,会同步忽略该 Issue。否则不受全局 Issue 忽略状态同步影响。 diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" deleted file mode 100644 index d2cc8fbad..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" +++ /dev/null @@ -1,18 +0,0 @@ -# OAuth管理 - -- 可**创建**、**编辑**、**清除**主流代码托管平台的Oauth应用配置,为使用者提供OAuth授权支持。 - -- 支持平台及如何创建OAuth应用: - - - 腾讯工蜂:[创建 OAuth 应用程序](https://code.tencent.com/help/oauth2/) - - GitHub:[创建 OAuth 应用程序](https://docs.github.com/cn/developers/apps/building-oauth-apps/creating-an-oauth-app) - - Gitee:[创建 OAuth 应用程序](https://gitee.com/api/v5/oauth_doc#/list-item-3) - - GitLab:[创建 OAuth 应用程序](https://docs.gitlab.com/ee/integration/oauth_provider.html) - -![OAuth管理](../../../images/manage_oauth_01.png) - -![OAuth管理](../../../images/manage_oauth_02.png) - -::: tip -配置OAuth应用时,回调地址栏需填入当前TCA平台配置的域名或IP地址(如当前页面非80端口,需要显式指定端口号),作为Git平台上OAuth应用的回调地址。 -::: diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" deleted file mode 100644 index 82db6162f..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 分析记录管理 - -- 可查看平台**全部分析记录**。 - -- 可点击查阅**分析记录详情**。 - -![分析记录列表](../../../images/manage_job_01.png) \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" deleted file mode 100644 index 68a879e2b..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 团队管理 - -- 可查看平台创建的团队列表,并提供了相应筛选 - -- 可**禁用**、**恢复**团队 - -![团队列表](../../../images/manage_org_01.png) - -![团队操作](../../../images/manage_org_02.png) \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" deleted file mode 100644 index 0b62da6b1..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 工具管理 - -- 可查看**全部工具**(包含平台提供工具、团队自定义工具)。 - -- 可**查看**、**编辑**工具。 - -- 可变更工具**权限状态**。 - -![工具管理](../../../images/manage_tool_01.png) - -::: tip -工具的权限状态仅能由**平台管理员**进行变更调整,需谨慎调整 - -- **团队内可用**:即工具配置了可用团队白名单的团队可以使用该工具,默认创建工具的团队已在白名单内 - -- **全平台可用**:即不同团队都可见可用该工具 - -- **支持自定义规则,全平台可用**:即该工具不同团队都可见可用,且支持用户添加团队所需的自定义规则,该自定义规则存在团队隔离,仅团队内可以,其他团队不可使用 -::: \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" deleted file mode 100644 index b51f8f02b..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 用户管理 - -- 可**查看**、**编辑**、**创建**平台用户。 - -- 可配置用户的**登录密码**、**用户级别**、**超级管理员**等。 - -![用户列表](../../../images/manage_user_01.png) - -![用户编辑](../../../images/manage_user_02.png) \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" deleted file mode 100644 index 3a23e9ddc..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" +++ /dev/null @@ -1,14 +0,0 @@ -# 节点管理 - -- 可查看**常驻节点状态**,包含**公共节点**和**团队节点**。 - -- 可**查看**、**编辑**、**删除**常驻节点。 - -- 可配置节点**工具进程**。 - -- 可配置**节点标签** - -![节点管理](../../../images/manage_node_01.png) -![节点管理](../../../images/manage_node_02.png) -![节点管理](../../../images/manage_node_03.png) -![节点管理](../../../images/manage_node_04.png) \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" deleted file mode 100644 index 3f6e4fbf2..000000000 --- "a/web/packages/tca-document/en/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 项目管理 - -- 可查看平台创建的项目列表,并提供了提供相应筛选 - -- 可**禁用**、**恢复**项目 - -![项目列表](../../../images/manage_team_01.png) \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" deleted file mode 100644 index 274a04e62..000000000 --- "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 团队说明 - -![成员权限](../../../images/team_member.png) - -## 层级关系 - -**团队** > **项目** > **代码库** > **分支项目** - -您可以创建一个团队,并可以在团队中创建多个项目来进行项目区分和项目管理。可以在一个项目中创建多个代码库进行代码分析。 - -## 权限控制 - -- 团队成员分为管理员和普通成员两类。团队管理员具备团队全部权限。 - -- 项目成员分为管理员和普通成员两类。项目管理员具备项目全部权限。 - -成员权限的区分,具体点击查看[成员权限](成员权限.md) - -## 邀请团队成员 - -管理员可以通过成员管理为您的团队添加成员,通过分享邀请链接的方式邀请您的团队。 diff --git "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" "b/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" deleted file mode 100644 index d4dfc5d66..000000000 --- "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 成员权限 - -## 团队成员 - -![成员权限](../../../images/team_member.png) - -团队成员分为**团队管理员**和**团队普通成员**两类。 - -**团队管理员**:可以邀请其他成员加入团队,具备团队内所有权限。 - -**团队普通成员**:可以创建项目,可以访问自己有权限的项目。创建项目的人会自动成为这个项目的项目管理员。 - -## 项目成员 - -项目成员分为**项目管理员**和**项目普通成员**。 - -**项目管理员**:具备项目内全部权限。 - -**项目普通成员**:可以查看项目内的配置信息和分析结果等各项信息,并且可以启动分析,但是无其他操作权限。 diff --git "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" "b/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" deleted file mode 100644 index e9684cd13..000000000 --- "a/web/packages/tca-document/en/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" +++ /dev/null @@ -1,105 +0,0 @@ -# 节点与标签 - -除了使用**公共节点**执行代码分析外,团队还可以利用**团队标签**注册并使用**团队节点**。 - -## 名词释义与特点 - -- 团队节点是**团队注册并管理**的**私有**节点。 - -- 团队节点**仅会运行**当前团队所属的分析任务。 - -- 团队标签是用于关联节点机器与分析项目。 - ::: tip - 当一个分析项目在方案中配置运行环境为团队标签后,该项目创建的任务就会下发到团队标签关联的节点机器上运行 - ::: - -## 适用场景 - -1. 业务项目**不想**在公共机器上**排队**等待 - -2. 业务项目**代码比较敏感**,不能在公共机器上运行 - -3. 业务项目需要**依赖特定**的**机器环境**(比如CPU架构、操作系统等) - -4. ... - -以上场景,均可考虑使用团队节点,业务团队提供机器资源接入作为团队节点,仅分析自己业务的代码库,**保证执行效率**,**保护源码不泄漏**,**支持项目特殊依赖**等 - -## 团队节点注册 - -- 根据环境下载客户端二进制文件或拉取源码,参考[客户端](../客户端/配置说明.md)。 - -- 通过终端启动客户端: - - - 客户端二进制启动 - - ```bash - ./codepuppy start -t TOKEN --org-sid ORG_SID - ``` - - - 客户端源码启动 - - ```bash - python3 codepuppy.py start -t TOKEN --org-sid ORG_SID - ``` - - ::: tip - 1. TOKEN 可以从平台**个人中心-个人令牌**页面获取 - 2. ORG_SID 可以从**页面链接**中获取 - ::: - -## 团队节点管理 - -完成团队节点注册后,可以在当前团队下看到对应的节点信息,同时**需要进行配置** - -::: warning -- 团队节点**首次注册**时,需要手动在平台上配置**所属标签**、**节点可用性**、**工具进程**等。 -- 将节点的**节点可用性**调整为**活跃**后,运行客户端节点的终端会输出**心跳上报成功**的日志 -::: - -- 首次注册团队节点,节点状态为不可用 - - ![注册团队节点](../../../images/org_node_manager_1.png) - -- 调整后的节点 - - ![注册团队节点](../../../images/org_node_manager_2.png) - -- 配置节点关联的工具进程: - - ![配置工具进程](../../../images/org_node_process.png) - -::: tip -1. 团队节点使用的**所属标签**均为当前团队内创建的标签,可参见[团队标签管理](#团队标签管理) -2. 团队标签可以参考`CodeDog`标签为不同的系统类型(Linux、MacOS、Windows)建立标签,比如`专属标签-Linux`、`专属标签-Mac`等 -::: - -### 团队节点执行任务范围 - -::: warning 使用团队节点运行分析任务的前提 -对应分析项目使用的分析方案中,需要配置分析方案中的**运行环境**为该团队节点配置的所属标签。 -::: - -::: warning 团队节点执行的任务范围取决于该节点的负责人 -- 如果节点负责人为团队管理员,该节点可以执行当前团队所有项目的分析任务 -- 如果节点负责人为项目管理员,该节点只能运行指定项目下的分析任务 -- 如果节点负责人为部分代码库的管理员,该节点只能运行对应代码库的分析任务 -::: - - -## 团队标签管理 - -您可以创建一个团队标签,并配置到您的团队节点和您的分析方案中 - -- 创建团队标签。 - - ![创建团队标签](../../../images/org_tag_manager.png) - -- 配置团队节点所属标签。 - - ![节点配置团队标签](../../../images/org_tag_node.png) - -- 配置分析方案运行环境。 - - ![方案配置团队标签](../../../images/org_tag_scheme.png) - diff --git "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" "b/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" deleted file mode 100644 index eff0e9571..000000000 --- "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 常驻节点分析 - -::: tip -TCA客户端除了通过`localscan`命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。 - -和本地分析一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -## 使用场景 - -- 希望通过并行执行分析来提高分析效率 - -- 希望尽量使用公共资源或使用专机资源 - -## 前置步骤 - -公共/专有机器上具备客户端。 - -如果是开源版客户端,需要配置相关环境和依赖,可查阅[开源版客户端使用说明](配置说明.md#开源版客户端使用说明)。 - -## 常驻节点配置 - -### 配置 `config.ini` 文件 - -- 将``替换成实际的serve ip(可包含端口号)。 - -### 启动代码分析常驻节点 - -- 从TCA前端页面中获取 `token`,前往 **个人中心-个人令牌-复制Token** - - ::: tip - 作为公共节点:token需要具有超级管理员权限,如使用`CodeDog`账户的`token`。 - - 可以通过[用户管理页面](../后台管理/后台管理说明.md)查看到哪些用户是超级管理员。 - - 作为专机节点:该节点仅能分析该`token`具有权限的项目。 - ::: - -- 进入到`client`目录下,执行命令:`python3 codepuppy.py -l codepuppy.log start -t ` - -- 启动后,可以在命令行输出或`codepuppy.log`中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -### 配置节点 - -常驻节点首次启动后,需要到节点管理页面设置节点状态(默认为`不可用`),将其设置为**`活跃`**,用于接收和执行任务。 - -- 进入TCA节点管理页面。`管理入口`-`节点管理` - - 可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 - - ::: tip - 常驻节点首次启动后,需将节点状态从**不可用(失效)**状态切换到**活跃(在线)**状态 - ::: - -- 可以进入**工具进程配置**页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 - -- **节点所属标签**会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 diff --git "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" "b/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" deleted file mode 100644 index 83e6e11a4..000000000 --- "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" +++ /dev/null @@ -1,73 +0,0 @@ -# 本地分析 - -## 使用场景 - -- 希望在本地随时分析。 - -- 如果公共机器无法满足编译环境的情况,复用本地编译环境。 - -- 如果对代码安全有要求也推荐使用本地分析。 - -## 前置步骤 - -本地具备客户端。 - -如果是开源版客户端,需要配置相关环境和依赖,可查阅[开源版客户端使用说明](配置说明.md#开源版客户端使用说明)。 - -## 分析配置 - -### 配置客户端 `config.ini` 文件 - -将 `` 替换成实际的serve ip(可包含端口号) - -### 配置客户端 `codedog.ini` 文件 - -- `token`,必填项。从TCA前端页面中获取,前往 **个人中心-个人令牌-复制Token** - -- `org_sid`,团队编号,必填项。可以从TCA前端项目页面URL获取。 - -- `team_name`,项目名称,必填项。可以从TCA前端项目页面URL获取。 - - ```bash - # 如 - http://{域名}/t/{org_sid}/p/{team_name}/profile - ``` - -- `source_dir`,本地代码目录路径,必填项。绝对路径。 - -- 其他参数 - - 按需填写其他可选项,也可以不填,按默认配置执行 - -## 启动代码分析 - -### 源码下启动分析 - -- 进入到`client`目录下 - -- 执行命令:`python3 codepuppy.py localscan` - -### docker下启动分析 - -#### 直接使用docker运行 - -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -#### 使用docker内bash终端运行 - -- 通过以下方式,进入容器内的bash终端后,通过命令行启动client代码: -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash -# 进入容器内终端,通过命令行执行扫描 -python3 codepuppy.py localscan -``` diff --git "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" "b/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" deleted file mode 100644 index 8cbe12b5a..000000000 --- "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" +++ /dev/null @@ -1,26 +0,0 @@ -## 在线分析 - -在线分析即是通过Server端将分析任务注册到执行队列中,并将任务分配到平台配置的常驻节点上,在常驻节点执行分析,分析完毕后将分析结果上报入库。 - -::: tip -平台需要存在常驻节点,请查阅 [常驻节点分析](./常驻节点分析.md) - -否则任务因没有机器而无法完成分配,超时后任务会注销。 -::: - -## 客户端分析 - -客户端分析即是本地分析,可直接配置本地的客户端配置文件,或在平台上配置好对应信息后,下载配置文件,替换客户端配置问题,并启动客户端分析。分析完毕后会将数据上报入库。 - -- 下载配置文件 - - ![下载配置文件](../../../images/start_scan_03.png) - -- 替换客户端配置文件,并启动客户端分析。 - -::: tip -本地需要下载客户端,请查阅 - -- [部署与配置客户端](../../quickStarted/deployClient.md) -- [客户端使用说明文档](./本地分析.md) -::: \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" "b/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" deleted file mode 100644 index 34bd7bc6e..000000000 --- "a/web/packages/tca-document/en/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" +++ /dev/null @@ -1,158 +0,0 @@ -# TCA Client - -## 一、基础配置 - -### 1. 机器配置推荐 - -| 操作系统 | 推荐配置 | -| --------: | :------------------------------------------- | -| Linux | 8核16G内存,硬盘空间256G(可用空间不低于100G) | -| Mac | 8核16G内存,硬盘空间256G(可用空间不低于100G) | -| Windows | 8核16G内存,硬盘空间256G(可用空间不低于100G) | - -以上为推荐配置,实际情况需要考虑扫描对象代码库的大小,按实际情况增加磁盘空间。 - -### 2. 配置client/config.ini文件 - --(1)将``替换成实际的serve ip(可包含端口号)。 - --(2)国内使用github拉取网络较慢,推荐使用腾讯工蜂拉取,需要修改以下配置: - -- 修改 TOOL_CONFIG_URL= -- 前往[腾讯工蜂网站](https://git.code.tencent.com)注册账号,作为拉取工具使用(已经注册过的可以直接使用) -- 将腾讯工蜂的账号密码填写到`TOOL_LOAD_ACCOUNT`中(由于腾讯工蜂的开源仓库也要求使用账号才能拉取,所以此处必须填写账号密码) - -### 3. 配置client/codedog.ini文件(分布式节点模式无需配置) - -填写以下必填项:`token`,`org_sid`,`team_name`,`source_dir` - -| 字段名 | 填写说明 | -| --------: | :------------------------------------------- | -| `token` | 从tca页面获取,前往[个人中心]-[个人令牌]-复制Token | -| `org_sid`(团队编号) | 从tca项目概览页面URL中获取,项目概览URL格式:`http://{域名}/t/{org_sid}/p/{team_name}/profile` | -| `team_name`(项目名称) | 同上 | -| `source_dir` | 本地代码目录路径 | - -其他可选项按需填写。 - -## 二、使用docker环境快速体验 - -:::tip -适用于快速上手体验。使用docker运行,可以免去客户端环境依赖的安装,避免环境兼容性问题。 - -但是由于环境受限于docker,会无法复用本地的编译环境,部分需要编译的工具无法使用。 -::: - -### 1. 下载和安装Docker - -参考Docker官方文档:[Docker下载和安装](https://docs.docker.com/get-started/) - -### 2. 构建docker镜像 - -在`client`目录下,执行以下命令:`docker build -t tca-client .` - -### 3. 执行docker容器,扫描代码,可选以下两种方式 - -#### (1)直接使用docker运行 - -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -#### (2)使用docker内bash终端运行 - -- 通过以下方式,进入容器内的bash终端后,通过命令行启动client代码: -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash -# 进入容器内终端,通过命令行执行扫描 -python3 codepuppy.py localscan -``` - -## 三、使用本地机器环境运行 - -:::tip -适用于深度体验,可以复用本地编译环境,使用编译型代码分析工具。 - -可能会有系统环境兼容问题。 -::: - -### 1. 安装Python环境和第三方库 - -- (1) 预装Python3.7、pip,支持 `python3` 和 `pip3` 命令 -- (2) 安装依赖:`pip3 install -r client/requirements/app_reqs.pip` - -### 2. 安装第三方工具 - -- (1) 进入到`client/requirements`目录 -- (2) 在命令行中执行安装脚本`install.sh`(linux/mac环境)或`install.bat`(windows环境) - -### 3. 启动代码分析 - -- (1) 进入到`client`目录下 -- (2) 执行命令:`python3 codepuppy.py localscan` - -## 四、使用分布式节点模式执行客户端 - -:::tip - -- CA客户端除了通过`localscan`命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。 -- 和本地执行任务一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -### 1. 安装Python环境和第三方库 - -- (1) 预装Python3.7、pip,支持 `python3` 和 `pip3` 命令 -- (2) 安装依赖:`pip3 install -r client/requirements/app_reqs.pip` - -### 2. 安装第三方工具 - -- 进入到`client/requirements`目录 -- 在命令行中执行安装脚本`install.sh`(linux/mac环境)或`install.bat`(windows环境) - -### 3. 启动代码分析节点 - -- (1)从tca页面`个人中心`-`个人令牌`-复制Token -- (2)进入到`client`目录下,执行命令:`python3 codepuppy.py -l codepuppy.log start -t ` -- (3)启动后,可以在命令行输出或`codepuppy.log`中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -### 4. 配置节点 - -- 从tca页面`管理入口`-`节点管理`,可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 -- 可以进入工具进程配置页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 -- 节点所属标签会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 - -## 五、其他配置与用法 - -### 1. 配置使用本地工具 - -:::warning -如果由于网络原因,执行时无法从github自动拉取工具,或拉取比较慢,可以参考基础配置腾讯工蜂工具地址,或使用以下方式预先下载好工具,配置使用本地工具目录。 -::: - -- (1)下载工具配置库 `https://github.com/TCATools/puppy-tools-config.git` ,存放到 `client/data/tools`目录下(如果未生成,可先创建该目录)。 -- (2)根据当前机器操作系统,查看`puppy-tools-config`目录下的`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件,将`[tool_url]`中声明的所有工具下载到 `client/data/tools`目录下。 -- (3)填写`client/config.ini`中的配置:`USE_LOCAL_TOOL`=`True`,即可使用下载好的本地工具,不自动拉取和更新工具。 - -### 2. 使用自建git server存放工具 - -:::warning -如果自己搭建了一套git server,可以将工具配置库 `https://github.com/TCATools/puppy-tools-config.git` 以及里面声明的工具仓库,存放到自建git serevr上。 -::: - -- (1)将工具配置库 `https://github.com/TCATools/puppy-tools-config.git` 上传到自建git仓库。 -- (2)按所需的操作系统,将`puppy-tools-config`仓库下的`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件中`[tool_url]`声明的所有工具库,上传到自建git仓库。 -- (3)修改`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件中`[base_value]`中的`git_url`为自建git server地址。 -- (4)修改`client/config.ini`中的`TOOL_CONFIG_URL`为自建git server的`puppy-tools-config`仓库地址。 -- (5)填写`client/config.ini`中的`[TOOL_LOAD_ACCOUNT]`配置,输入有拉取权限的用户名密码,即可使用自建git server拉取工具。 - -### 3. git lfs带宽和存储配额不够问题 - -- 如果git拉取工具时,出现git lfs拉取失败,可能是lfs带宽和存储配额不够,可以打开对应的工具github页面,通过`Download ZIP`的方式下载工具压缩包,再解压到`client/data/tools`目录下。 diff --git "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" "b/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" deleted file mode 100644 index 45082ec7f..000000000 --- "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" +++ /dev/null @@ -1,52 +0,0 @@ -# 工具管理说明 - -腾讯云代码分析平台目前已集成众多自研、知名开源工具,并采用分层分离的架构,可以快速对接企业内部团队研发的工具,并将其集成到平台内供企业内部团队使用,满足快速自助的管理工具。 - -- 按工具来源划分,工具包含**平台提供**的工具,以及**团队接入**的工具。 - - **平台提供工具**:由腾讯云代码分析平台提供的一系列自研、知名开源工具,此类工具都为公开工具,任何团队都可以使用此工具及工具规则进行代码分析。 - - **团队接入**:由团队自行接入的工具,默认该工具仅能在团队内使用,如需跨团队使用或任何团队都可以使用需联系平台管理员进行配置。 - -- 按工具使用划分,工具包含**可自定义规则工具**、**可使用工具**两种。 - - **可自定义规则工具**:该工具任何团队都可以使用,且该工具可以支持添加团队所需的自定义规则。如`RegexScan`工具,各个团队都可以使用该工具提供的规则,也可以自定义规则,此自定义规则团队隔离。 - - **可使用工具**:该工具团队内可使用,但不能添加自定义规则 - -::: tip -目前开源版仅**`RegexFileScan`、`RegexScan`**等两款工具支持用户自定义规则 - -需平台管理员在**后台管理**-**工具管理**中找到对应工具,并将其权限状态调整为**支持自定义规则**。 -::: - -## 自定义工具 -### 工具白名单 -默认自定义工具只能当前团队内使用,添加 `工具白名单` 后可以让其他团队使用。 - -## 使用场景说明 - -::: tip -添加工具、添加工具规则、添加自定义规则等均需团队内管理员可操作。分析。 -::: - ---- - -【用户 A1】【用户 A2】为【团队 O1】的管理员,【用户 A3】为【团队 O2】的普通成员。 - -【用户 B1】【用户 B2】为【团队 O2】的管理员,【用户 A3】为【团队 O2】的普通成员。 - -### 场景 1 - -- 【用户 A1】在工具管理页面添加了【工具 T1】,该工具为团队内工具; -【用户 A1】【用户 A2】均可操作该工具,如修改工具信息、添加工具规则等,【用户 A3】仅可以使用该工具,如在规则配置页面添加该工具规则; - -- 由于【工具 T1】目前仅【团队 O1】可用,【团队 O2】中无法看到此工具,即【团队 O2】内的成员无法使用该工具。 -- 如需【工具 T1】也让【团队 O2】使用有两种解决方法:1. 【工具 T1】将【团队 O2】加入使用白名单;2. 向平台发起申请,由平台管理员将【工具 T1】调整为全部团队都可使用。 - -### 场景 2 - -- 【用户 A3】在工具管理页面发现了可自定义规则的工具,如`正则工具 RegexScan`,进入工具-自定义规则栏,发现没有添加规则的入口; -- 由于【用户 A3】仅为普通成员权限,因此无法添加规则,此时需要【团队 O1】的管理员才能操作; -- 添加【自定义规则 R1】完成后,团队内全部成员均可使用该自定义规则,如在规则配置页面添加该自定义规则; -- 由于【自定义规则 R1】是团队隔离的,即【团队 O1】创建的自定义规则,在【团队 O2】中并看不到,且无法使用该规则; -- 如需【自定义规则 R1】也让【团队 O2】使用,则仅能向工具方发起申请,由工具方将该自定义规则调整为工具规则。 diff --git "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" "b/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" deleted file mode 100644 index 249135666..000000000 --- "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" +++ /dev/null @@ -1,190 +0,0 @@ -# 自定义工具 - -腾讯云代码分析平台支持用户自助添加代码分析工具。 - -适用场景:自定义规则无法满足团队业务复杂需求,需要更多的代码逻辑来匹配目标代码的情况。通常需要团队业务方自行实现对应代码分析工具。 - -只需要几步操作: - -1. 编写代码,实现扫描工具逻辑 -2. 提交工具到 git 代码库 -3. 在页面创建新工具 -4. 为工具添加规则 -5. 将工具配置到执行节点 -6. 在项目分析方案中添加规则 - -## 自定义工具步骤说明 - -### 第一步,编写代码,实现分析工具逻辑 - -根据需要匹配的目标代码场景,编写对应的工具逻辑。 -可以参考 Python 实现的 [Demo 项目](https://github.com/TCATools/demo_tool)。 - -**必要:** - -- **运行方式**:支持命令行执行,比如 python run.py 或 run.exe,执行命令的工作目录为工具代码的根目录。 - -- **运行环境说明**: - - 建议将工具打包编译成可执行程序,拉取下来直接可以执行。 - - 如果工具需要在特定的环境中运行,比如python、java环境,平台提供了丰富的工具依赖包,可以在`工具管理`-`工具依赖`中查看,创建工具时可供选择,执行时会自动配置好依赖环境。 - - 如果现有的工具依赖包未支持所需依赖,也可以创建新的工具依赖使用。 - -- **平台已提供的环境变量** - - - 获取及使用方式请参考 [Demo 项目](https://github.com/TCATools/demo_tool)。 - ``` - SOURCE_DIR:要扫描的代码目录路径 - DIFF_FILES: 值为一个json文件路径,文件内容为增量扫描的文件列表(增量扫描时可用) - SCAN_FILES: 值为一个json文件路径,文件内容为需要扫描的文件列表(增量或全量扫描均可用) - TASK_REQUEST: 值为一个json文件路径,文件内容为当前扫描任务参数 - ``` - -- **工具命令声明** - - 在工具仓库根目录下,添加一个`tool.json`文件,声明工具的检查和扫描命令,比如: - ```json - { - "check_cmd": "python src/main.py check", - "run_cmd": "python src/main.py scan" - } - ``` - 参数说明: - - `check_cmd`: - - 功能:判断当前执行环境是否满足工具要求(如果不需要检查,也可以没有这个命令)。 - 比如某些工具只能在linux下执行,需要判断当前是否为linux环境。 - - 输出:将判断结果输出到`check_result.json`文件中,文件内容为`{"usable": true}`或`{"usable": false}`。 - - `run_cmd`: - - 功能:扫描代码,执行自定义检查器逻辑(该命令必须存在)。 - - 输出:按照指定格式,输出结果到`result.json`文件中。 - -- **工具输出格式要求** - - - 将扫描结果输出到当前工作目录下的`result.json`文件中(Python 示例代码) - ```python - import json - with open("result.json", "w") as fp: - json.dump(result, fp, indent=2) - ``` - - - `result.json` 文件格式如下: - ```json - [ - { - "path": "文件绝对路径", - "line": "行号,int类型", - "column": "列号, int类型,如果工具没有输出列号信息,可以用0代替", - "msg": "提示信息", - "rule": "规则名称,可以根据需要输出不同的规则名", - "refs": [ - { - "line": "回溯行号", - "msg": "提示信息", - "tag": "用一个词简要标记该行信息,比如uninit_member,member_decl等,如果没有也可以都写成一样的", - "path": "回溯行所在文件绝对路径" - }, - ... - ] - }, - ... - ] - ``` - - **`refs`** 字段说明: - - 非必需项,可无。该字段记录问题回溯路径信息。比如当前行的代码问题,是经过上下文的三行代码执行路径而导致的,可以将这三行的位置及提示信息,按顺序添加到 refs 数组中。 - -### 第二步,提交工具到 git 代码库 - -- 创建代码库,将工具源代码或编译打包后的可执行文件,提交到代码仓库中(建议提交到master分支,TCA默认拉取的是master分支)。 - -- 建议代码库中加入 README.md 文件,说明工具功能和维护人。 - -- 后续需要修改工具实现逻辑,可以直接更新代码库,TCA 平台在执行该工具时,会自动拉取最新工具代码版本。 - -### 第三步,在工具管理页面中创建工具 - -- 进入工具管理页面,点击创建工具 - - ![enter image description here](../../../images/customtool_01.png) - -- 填写工具信息 - - ![enter image description here](../../../images/customtool_02.png) - - **部分参数说明:** - - - **工具仓库地址**,即前述步骤中提交的工具 git 代码库地址,默认拉取的是master分支,如果是其他分支,需要在仓库地址后加上`#分支名`,比如:`https://github.com/xxx/xxx.git#main` - - - **工具认证**,授权拉取工具仓库的权限 - - - **执行命令**,该命令会在工具根目录下执行 - - - **环境变量**,工具执行所需的环境变量 - - - **License**,如果是开源工具,填写工具遵循的开源协议,或者填写自研共建 - - - **是否为编译型工具**,表示在使用该工具对用户代码进行分析时,是否要求代码需要编译或可执行编译 - - -- 添加工具依赖 - - ![enter image description here](../../../images/customtool_03.png) - - 添加完成后,会展示已添加的依赖方案: - - ![enter image description here](../../../images/customtool_04.png) - -**工具依赖说明:** -- 比如当前的demo工具,只需要依赖python3运行,而且支持在linux x86_64、linux arm64、mac和windows下执行,那么只需要配置一个依赖方案(如上图),并配置为默认方案。在不同的操作系统中,会自动加载对应操作系统的python环境。 -- 如果需要根据扫描项目设置的环境变量,加载不同的依赖配置,则可以配置不同的判断条件,使用多个依赖方案。 - - -### 第四步,为工具添加规则 - -- 完成工具创建后,进入规则列表,为工具添加规则 - - ![enter image description here](../../../images/customtool_05.png) - -- 填写规则信息 - - **部分参数说明:** - - - **规则简介**:简要描述规则发现的是什么问题,扫描结果中会作为问题标题展示 - - - **详细描述**:可详细描述规则,以及规则的解决方式,建议附上解决案例 demo - - - **解决方法**:按照实际情况,说明该代码问题的解决方法,建议附上解决案例 demo - - - **规则参数**:如果不需要通过规则参数传递信息,可留空 - -### 第五步,将工具配置到执行节点 - -::: tip -需要联系平台管理员协助操作,在`管理入口`-`节点管理`中进入需要配置的机器节点的`工具进程配置`中,找到对应工具,勾选工具进程。 - -完成节点配置工具进程后,才能在项目中采用该工具进行分析。 -::: - -![enter image description here](../../../images/customtool_06.png) - -### 第六步,完成上述操作,在项目中使用工具规则 - -- 进入到项目中,在`分析方案`-`代码检查`进行规则配置。 - -- 点击添加规则,找到对应工具规则进行添加。 - -- 添加完成后,启动分析,为了将规则应用到所有代码文件,建议启动一次全量分析(增量分析只会分析自上次扫描后变更的文件)。 - -## 自定义工具权限说明 - -- **默认自定义工具仅团队管理员可操作,团队内所有成员可使用。** - - - 团队管理员才能创建工具,添加工具规则等,具备该工具全部权限 - - - 团队内所有成员可使用该工具规则,如在规则配置中添加此工具规则,团队普通成员仅只读权限 - -- **工具希望全平台使用?** - - 由于全平台使用的工具影响范围较大,建议团队先在团队内对工具进行充分测试,保障团队内工具的高有效性,如需全平台使用,需联系平台管理员进行申请 - - 平台管理员需对此工具进行审核,在确保工具的高有效性下可将此工具权限调整为全平台可使用 diff --git "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" "b/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" deleted file mode 100644 index 6912b5b43..000000000 --- "a/web/packages/tca-document/en/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" +++ /dev/null @@ -1,73 +0,0 @@ -# 自定义规则 - -自定义规则即由业务团队根据自身需求,由业务团队自行设计提供的规则。 - -## 自定义规则权限说明 - -- 工具需开放**支持自定义规则**权限,才可添加自定义规则。 - - - 当前平台提供的工具中,仅`RegexFileScan`、`RegexScan`两款工具支持使用用户自定义规则。 - - - 开放**支持自定义规则**权限,需平台管理员在**管理入口**-**工具管理**中找到对应工具,并将其权限状态调整为**支持自定义规则**。 - -- 自定义规则仅支持团队管理员添加,且默认仅团队内可见。 - - - 满足不同团队自定义规则可能存在的差异和隐私性。 - -- 如需将自定义规则加入工具默认规则,需联系工具提供方团队管理员添加。 - -## 平台提供的正则工具 RegexScan 说明 - -`正则工具 RegexScan` 即为开放了自定义规则功能的工具,可进入工具管理页面,搜索工具名称`RegexScan`,查看该工具已存在的规则以及根据团队业务需求,添加自定义规则。 - -适用场景:通过正则表达式,能够匹配到目标代码的情况。 - -### 自定义规则步骤 - -1. **根据团队业务需求设计正则表达式** - - ::: tip - 建议先测试好正则表达式是否正确,正则表达式测试网站推荐:[http://tool.oschina.net/regex](http://tool.oschina.net/regex) - - 规则示例: - - - 规则分析场景 - - 分析代码中的 usleep() 方法调用,如果参数小于 100 ,容易造成 CPU 使用率过高,造成性能浪费,判断为缺陷。 - - - 正则表达式 - - 匹配 usleep() 字符串,括号中的内容为 1 位或 2 位整数,那么正则表达式可以写成 `\busleep\s*\(\s*\d{1,2}\s*\)`,这里考虑了字符串中存在空格的情况。 - ::: - -2. **进入正则工具添加自定义规则** - - 进入工具管理页面,找到正则工具`RegexScan`,并点击进入自定义规则列表页,点击添加规则按钮。 - -3. **填写规则信息** - - **规则参数填写说明(必要):** - - 参数格式类似 ini 的格式, 也就是 key = value 的格式 - - - **【必要】** regex 参数,用于指定分析的正则表达式, 例如: `regex = \busleep\s*\(\s*\d{1,2}\s*\)`。 - - - **【必要】** msg 参数,用于展现 issue 说明, 例如: `msg = 函数方法%s 已经废弃,请使用 xxx 方法`。 - - msg 中的“%s”使用 regex 中的 group(用“()"括起来的部分)一一匹配。 - - 如果 regex 没有定义 group,则 msg 最多有一个%s, 并由整个 regex 匹配的字符串替代 - - 如果 msg 里没有包含“%s”,则直接显示 msg - - 如果 msg 没有提供,则默认为“发现不规范代码:%s”(不建议使用默认格式,太笼统) - - - **【可选填】** ignore_comment 参数,用于指定是否忽略注释代码,可选值:True、true、False、false 。例如 `ignore_comment=True`, 默认是 False - - - **【可选填】** include 参数,用于将指定分析文件匹配范围,使用 unix 的文件匹配格式,多项使用英文分号;隔开。例如 `include = path/to/dir;path/to/\*.cpp` - - - **【可选填】** exclude 参数,用于指定不分析的文件。格式参考 include 参数。 - -4. **将自定义规则添加到项目分析方案中** - - 添加完成,可在分析方案-代码检查-规则配置中添加该自定义规则 diff --git "a/web/packages/tca-document/en/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/web/packages/tca-document/en/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" deleted file mode 100644 index 70bdc82cd..000000000 --- "a/web/packages/tca-document/en/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" +++ /dev/null @@ -1,77 +0,0 @@ -# 快速启动一次代码分析 - -## 创建项目 - -- **创建团队并进入** - - ![创建团队](../../../images/create_team.png) - - :::tip - 还没有团队?点击了解[团队管理](../团队管理/团队管理.md) - ::: - -- **为团队创建一个项目,或选择一个已有项目,并进入项目内** - - ![创建项目](../../../images/create_team_group.png) - -## 完成代码库登记 - -- **完成代码库登记,并点击进入代码分析** - - ![代码库登记](../../../images/create_repo.png) - - ![进入代码分析](../../../images/start_scan_01.png) - -## 开启第一次代码分析 - -### 执行初始化创建 - - ![开始分析](../../../images/start_scan_02.png) - - ::: tip - - 1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 - 2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目,最终下载客户端分析配置文件,客户端执行代码分析。 - ::: - -### 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../../images/start_scan_06.png) - -#### 在线分析 - -在线分析即是通过Server端将分析任务注册到执行队列中,并将任务分配到平台配置的常驻节点上,在常驻节点执行分析,分析完毕后将分析结果上报入库。 - -::: tip -平台需要存在常驻节点,请查阅 [常驻节点分析](../客户端/常驻节点分析.md) - -否则任务因没有机器而无法完成分配,超时后任务会注销。 -::: - -#### 客户端分析 - -客户端分析即是本地分析,可直接配置本地的客户端配置文件,或在平台上配置好对应信息后,下载配置文件,替换客户端配置问题,并启动客户端分析。分析完毕后会将数据上报入库。 - -- 下载配置文件 - - ![下载配置文件](../../../images/start_scan_03.png) - -- 替换客户端配置文件,并启动客户端分析。 - -::: tip -本地需要下载客户端,请查阅 [客户端使用说明文档](../客户端/本地分析.md) -::: - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../代码检查/分析结果查看.md)等。 - -![分支概览](../../../images/start_scan_04.png) diff --git "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" "b/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" deleted file mode 100644 index fb93b011a..000000000 --- "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" +++ /dev/null @@ -1,60 +0,0 @@ -# 基于MinIO部署文件服务器 -TCA的``file``服务支持对接``MinIO``作为底层存储,将文件转发到已部署的MinIO平台上进行持久化存储 - -## 本地部署 -> 注意:如果之前已经使用本地进行存储,切换为MinIO后,之前已经上传的文件只能到服务部署的目录``server/projects/file/data``查看,不支持通过页面进行下载 - -### 前置步骤 -获取MinIO平台登录的账号密码,用于上传文件 - -### 配置步骤 -#### 1. 调整``file``服务的配置 -修改``server/configs/django/local_file.py``文件,取消以下代码的注释 - -``` -# MINIO -STORAGE = { - "CLIENT": os.environ.get("FILE_STORAGE_CLIENT", "MINIO"), # 存储方式 - "OPTIONS": { - "MINIO_ENTRYPOINT": os.environ.get("FILE_MINIO_ENTRYPOINT"), - "MINIO_ACCESS_KEY": os.environ.get("FILE_MINIO_ACCESS_KEY"), - "MINIO_SECRET_KEY": os.environ.get("FILE_MINIO_SECRET_KEY"), - } -} -``` - -修改``server/scripts/config.sh``文件,填写MinIO的信息 - -```bash -export FILE_MINIO_ENTRYPOINT= -export FILE_MINIO_ACCESS_KEY= -export FILE_MINIO_SECRET_KEY= -``` - -修改完配置后,如果服务已经正在运行,则执行以下命令重启服务 - -```Bash -$ cd server -$ ./scripts/deploy.sh start -``` - -#### 2. 修改nginx服务的配置文件 -删除nginx已有的文件服务器配置文件``/etc/nginx/conf.d/tca_file_local.conf``文件,然后执行 - -```bash -rm /etc/nginx/conf.d/tca_file_local.conf -ln -s $CURRENT_PATH/configs/nginx/tca_file_minio.conf /etc/nginx/conf.d/tca_file_local.conf -``` - -> 也可以修改``server/scripts/init_config.sh`` ->```Bash -> # 注释这一行 -> ln -s $CURRENT_PATH/configs/nginx/tca_file_local.conf /etc/nginx/conf.d/tca_file_local.conf -> # 取消注释这一行 -> ln -s $CURRENT_PATH/configs/nginx/tca_file_minio.conf /etc/nginx/conf.d/tca_file_local.conf ->``` - -修改完配置后,如果nginx已经正在运行,则执行``nginx -s reload`` - -### 结尾 -以上两个步骤操作完成后,就可以通过``MinIO``存储文件了~ \ No newline at end of file diff --git "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" "b/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" deleted file mode 100644 index 1eef61455..000000000 --- "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" +++ /dev/null @@ -1,15 +0,0 @@ -在实际的生产环境的部署过程中,团队的MySQL的管理员可能不会给到应用账号create等比较敏感的权限,这种情况下,我们可以通过手动迁移数据的方式起到和等同Django migrate的效果。 - -操作步骤: - -1. 进入Server服务工作目录后(假设工作目录为 ``/data/CodeAnalysis/server/``,以下路径均为工作目录内的相对路径) -2. 在开发环境一个有全部权限的MySQL地址,初始化数据(MySQL版本运行版本:5.7) - - 执行``vi ./scripts/config.sh``:填写一个有全部权限的MySQL数据库地址和Redis信息以及根据需要调整配置信息,主要的工程配置已提供默认值,字段说明可以查看[文档](../server/README.md) - - 执行``bash ./scripts/deploy.sh init``:初始化DB、安装依赖和运行初始化脚本 - - 使用MySQLDump工具导出表结构与数据:``mysqldump -u user -p –databases codedog_main codedog_analysis codedog_file codedog_login > codedog_all.sql`` -3. 在生产环境建数据库,详情见:``server/sql/init.sql`` -4. 连接MySQL,导入数据: - - 临时关闭外键检查: ``SET SESSION FOREIGN_KEY_CHECKS=0``,否则会因为数据中有外键关联导致导入失败 - - 导入表结构与数据: ``source /youdir/codedog_all.sql;`` - - 开启外键检查: ``SET SESSION FOREIGN_KEY_CHECKS=1`` -5. 启动服务: 直接执行 ``bash ./scripts/deploy.sh start``,无需执行 ``init``方法,否则会导致数据重复写入 diff --git "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/server.md" "b/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/server.md" deleted file mode 100644 index 8d1b25a01..000000000 --- "a/web/packages/tca-document/en/guide/\346\234\215\345\212\241\347\253\257/server.md" +++ /dev/null @@ -1,133 +0,0 @@ -# TCA Server - -## 工程结构 -TCA Server由Main、Analysis、Login、File、ScmProxy五个微服务组成,主要技术栈为Django+uwsgi+nginx - -## 配置说明 - -注意:以下配置内容可以参考 [config.sh](https://github.com/Faberiii/CodeAnalysis/blob/main/server/scripts/config.sh)文件进行查阅,使用时主要关注 MySQL、Redis 的配置,其他配置均已提供默认值,可以根据需要进行调整 - -### Main服务 -框架配置: - -- MAIN_DEBUG_MODE: Main服务的Debug模式,``true/false`` -- MAIN_SECRET_KEY: Main服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Main服务DB配置: - -- MAIN_DB_NAME:Main服务的数据库名称 -- MAIN_DB_USER:Main服务的数据库用户名 -- MAIN_DB_PASSWORD:Main服务的数据库密码 -- MAIN_DB_HOST:Main服务的数据库地址 -- MAIN_DB_PORT:Main服务的数据库端口号 - -Main服务Redis配置: - -- MAIN_REDIS_HOST:Main服务访问的Redis地址 -- MAIN_REDIS_PORT:Main服务访问的Redis端口号 -- MAIN_REDIS_PASSWD:Main服务访问的Redis密码 -- MAIN_REDIS_DBID:Main服务访问的Redis DB编号,默认为1(Analysis服务默认访问0号DB) - -服务交互配置: -- MAIN_SENTRY_DSN:Main服务异常日志上报至sentry配置 -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token -- FILE_SERVER_TOKEN:文件服务器访问Token -- CODEDOG_TOKEN:CodeDog默认访问的Token - - -### Analysis服务 -框架配置: - -- ANALYSIS_DEBUG_MODE: Analysis服务的Debug模式,``true/false`` -- ANALYSIS_SECRET_KEY: Analysis服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Analysis服务DB配置: - -- ANALYSIS_DB_NAME:Analysis服务的数据库名称 -- ANALYSIS_DB_USER:Analysis服务的数据库用户名 -- ANALYSIS_DB_PASSWORD:Analysis服务的数据库密码 -- ANALYSIS_DB_HOST:Analysis服务的数据库地址 -- ANALYSIS_DB_PORT:Analysis服务的数据库端口号 - -Analysis服务Redis配置: - -- ANALYSIS_REDIS_HOST:Analysis服务访问的Redis地址 -- ANALYSIS_REDIS_PORT:Analysis服务访问的Redis端口号 -- ANALYSIS_REDIS_PASSWD:Analysis服务访问的Redis密码 -- ANALYSIS_REDIS_DBID:Analysis服务访问的Redis DB编号,默认为0(Main服务默认访问1号DB) - -服务交互配置: -- ANALYSIS_SENTRY_DSN:Analysis服务异常日志上报至sentry配置 -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - - -### Login服务 -框架配置: - -- LOGIN_DEBUG_MODE: Login服务的Debug模式,``true/false`` -- LOGIN_SECRET_KEY: Login服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Login服务DB配置: - -- LOGIN_DB_NAME:Login服务的数据库名称 -- LOGIN_DB_USER:Login服务的数据库用户名 -- LOGIN_DB_PASSWORD:Login服务的数据库密码 -- LOGIN_DB_HOST:Login服务的数据库地址 -- LOGIN_DB_PORT:Login服务的数据库端口号 - -服务交互配置: -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - -注:配置文件中的pub_key与private_key生成方式可以参考以下方法: -```bash -$ ssh-keygen -t rsa -b 1024 -m PEM -f tca_login.key -$ openssl rsa -in tca_login.key -pubout -outform PEM -out tca_login.key.pub -$ cat tca_login.key # 作为private_key的内容 -$ cat tca_login.key.pub # 作为pub_key的内容 -``` - -### File服务 -框架配置: - -- FILE_DEBUG_MODE: File服务的Debug模式,``true/false`` -- FILE_SECRET_KEY: File服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -File服务DB配置: - -- FILE_DB_NAME:File服务的数据库名称 -- FILE_DB_USER:File服务的数据库用户名 -- FILE_DB_PASSWORD:File服务的数据库密码 -- FILE_DB_HOST:File服务的数据库地址 -- FILE_DB_PORT:File服务的数据库端口号 - -服务交互配置: -- FILE_SENTRY_DSN:File服务异常日志上报至sentry配置 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - -File存储引擎配置 -- FILE_STORAGE_CLIENT: 文件存储引擎,可选项:``LOCAL``/``MINIO``/``COS`` - - 当配置引擎为``LOCAL``,可以指定``FILE_STORAGE_DIR``文件存放的路径 - - 当配置引擎为``MINIO``,可以指定以下变量: - - FILE_MINIO_ENTRYPOINT:MINIO服务地址 - - FILE_MINIO_ACCESS_KEY:MINIO服务访问账号 - - MINIO_SECRET_KEY:MINIO服务访问密码 - - 当配置引擎为``COS``,可以指定以下变量 - - TENCENT_COS_APPID - - TENCENT_COS_SECRETID - - TENCENT_COS_SECRETKEY - - TENCENT_COS_REGION - - TENCENT_COS_ROOT_BUCKET:填写格式为bucket-appid - -### ScmProxy -服务配置: -- SCMPROXY_HOST:ScmProxy服务的HOST,默认为``0.0.0.0`` -- SCMPROXY_PORT:ScmProxy服务监听端口,默认为``8009`` -- SCMPROXY_SENTRY_URL:ScmProxy服务异常日志上报至sentry配置 -- SCMPROXY: 通过本环境变量去指定其他服务调用ScmProxy服务的地址,默认值为``127.0.0.1:8009`` diff --git a/web/packages/tca-document/en/quickStarted/FAQ.md b/web/packages/tca-document/en/quickStarted/FAQ.md deleted file mode 100644 index 481d771b8..000000000 --- a/web/packages/tca-document/en/quickStarted/FAQ.md +++ /dev/null @@ -1,387 +0,0 @@ -# 常见问题 - -:::tip -该Q&A文档会持续更新,非常欢迎您的建议与共建! - -如果您遇到任何未在此处列出的部署或使用问题,请在 GitHub issue 系统中进行搜索。如果仍未找到该错误消息,您可以通过[社区](../community/joingroup.md)提出问题,获得帮助。 -::: - -[[toc]] - -## Server常见问题与处理方法 - -### 1. 环境部署 - -#### 1.1 pypi下载超时或失败 - -如果在执行``pip install``环节出现以下错误,可以调整一下镜像源: - -```bash -WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='files.pythonhosted. org', port=443): Read timed out.(read timeout=15)") ' -``` - -该错误是访问官方``pypi``下载源时网络不通或者不稳定导致,可以通过以下方式调整: - -本地部署时,调整``pypi``下载源配置方式: - -```bash -mkdir ~/.pip/ -echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` - -Docker-Compose部署时,调整``pypi``下载源配置方式: - -```bash -vi server/dockerconfs/Dockerfile-common -``` - -调整文件中最后一行 ``RUN``指令 - -```bash -RUN mkdir -p log/ && \ - mkdir ~/.pip/ && \ - echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf && \ - pip install -U setuptools pip && \ - pip install -r requirements.txt -``` - -注:如果需要指定其他``pypi``下载源,可以将``https://mirrors.cloud.tencent.com/pypi/simple``进行替换 - -如果出现以下错误: - -```bash -WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')': /simple/setuptools/ -``` - -该错误是无法正常解析``pypi``访问域名,需要检查一下本地的dns配置是否正常 - -#### 1.2 Docker未安装或版本过低 - -TCA Server使用Docker-Compose依赖的Docker版本需要是``1.13.0``及以上,可以执行以下命令查看Docker版本 - -```bash -$ docker --version -Docker version 18.09.7, build 2d0083d -``` - -文档相关: - -- [Compose文件版本与对应的Docker版本说明文档](https://docs.docker.com/compose/compose-file/compose-versioning/) -- [CentOS安装Docker官方文档](https://docs.docker.com/engine/install/centos/) -- [Ubuntu安装Docker文档](https://docs.docker.com/engine/install/ubuntu/) - -#### 1.3 Docker-Compose启动失败 - -如果启动Docker-Compose输出以下错误: - -```bash -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -``` - -问题原因:可能镜像构建目录权限不足,导致异常。 -解决方案: - -1. 执行``docker-compose build``可以通过日志查看是哪个镜像构建异常 -2. 切换到具体目录执行``docker build .``可以看到详细错误信息,结合具体错误信息进行处理 -3. 收集常见的错误日志,整理相关解决方案(注:欢迎大家补充) - -文档相关: - -- [Docker-Compose官方安装文档](https://docs.docker.com/compose/install/) -- [Docker-ComposeV2官方安装文档](https://docs.docker.com/compose/cli-command/) - -#### 1.4 Docker镜像源下载超时或失败 - -目前TCA基础镜像是使用``python:3.7.12-slim``,该镜像是基于``debian bullseye(debian 11)``版本构建的,对应的源需要选择 ``bullseye`` 版本的源。 - -如果使用默认的下载源会报错或访问速度比较慢,可以调整``server/dockerconfs/Dockerfile-common``,指定其他国内下载源: - -```DockerFile -# FROM python:3.7.12-slim - -# 增加一下内容用于指定下载源 -RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak && \ - echo 'deb http://mirrors.tencent.com/debian/ bullseye main non-free contrib' > /etc/apt/sources.list && \ - echo 'deb http://mirrors.tencent.com/debian/ bullseye-updates main non-free contrib' >> /etc/apt/sources.list && \ - echo 'deb http://mirrors.tencent.com/debian-security bullseye-security main non-free contrib' >> /etc/apt/sources.list - -# ARG EXTRA_TOOLS=... -``` - -如果出现以下错误:``E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages`` -可以做以下检查,确认是什么原因: - -1. 检查一下本地服务器的时间配置是否正常 -2. 调整下载源 - -#### 1.5 Python安装或执行失败 - -使用Python执行时提示``ImportError: libpython3.7m.so.1.0: cannot open shared object file: No such file or directory``,该如何处理 - -1. 在本地安装Python的目录中查找该文件,比如Python的安装目录是``/usr/local/python3``,可以执行``find /usr/local/python3 -name "libpython3.7m.so.1.0"``,确认本地是否存在该文件 -2. 如果本地存在该文件,则执行以下命令:(注:需要将``/usr/local/python3``调整为本地实际的Python3安装路径) - - ```bash - # 链接构建产出的Python动态库 - $ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 - # 配置动态库 - $ ldconfig - ``` - -3. 如果本地不存在该文件,则可能需要重新安装Python3:(注:以下是将Python安装到``/usr/local/python3``,可以根据实际情况进行调整) - - ```bash - # 编译前配置,注意重点:需要加上参数 --enable-shared - $ ./configure prefix=/usr/local/python3 --enable-shared - ``` - -文档相关: - -- [CentOS安装Python3.7文档](https://github.com/Tencent/CodeAnalysis/blob/main/doc/references/install_python37_on_centos.md) -- [Ubuntu安装Python3.7文档](https://github.com/Tencent/CodeAnalysis/blob/main/doc/references/install_python37_on_ubuntu.md) - -#### 1.6 执行``compose_init.sh``脚本的``pip install``提示``sha256``不匹配错误 - -在构建镜像的``pip install``步骤提示以下报错时: - -``` -ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them. - setuptools from https://mirrors.cloud.tencent.com/pypi/packages/fb/58/9efbfe68482dab9557c49d433a60fff9efd7ed8835f829eba8297c2c124a/setuptools-62.1.0-py3-none-any.whl#sha256=26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8: - Expected sha256 26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8 - Got ddaacc49de5c08c09d744573240a9a49f24f65c5c72380e972433784caa68d98 -``` - -可以执行``export ORIGIN=normal``,然后再执行``./compose_init.sh`` ->注:执行``export``命令的作用是调整为``pypi``默认官方下载源进行``pip install`` - -#### 1.7 MacBook M1 使用 Docker-Compose报错 - -在M1机器上使用默认配置启动docker-compose,会出现``mysql``和``scmproxy``服务启动失败,需要做以下两步调整 - -1. 调整``docker-compose.yml``文件,修改MySQL的镜像版本: - - ```bash - # 默认: - image: mysql:5.7.24 - - # 调整后: - image: mariadb:10.5.8 - ``` - -2. 调整``server/dockerconfs/Dockerfile-common``文件,修改Python的镜像版本: - - ```bash - # 默认: - FROM python:3.7.12-slim - - # 调整后: - FROM amd64/python:3.7.12-slim - ``` - -#### 1.8 celery、gunicorn命令找不到 - -如果启动服务时,提示:``celery could not be found``或``gunicorn could not be found``,需要做以下检查 - -1. 执行``python -v``检查输出,确认当前python版本是否为python3.7 -2. 执行``pip install celery``和``pip install gunicorn``检查celery和gunicorn是否已经安装 -3. 如果已经安装,可以执行以下命令建立软链:(注:需要将``/usr/local/python3``调整为本地实际的Python3安装路径) - -```bash -ln -s /usr/local/python3/bin/gunicorn /usr/local/bin/gunicorn -ln -s /usr/local/python3/bin/celery /usr/local/bin/celery -``` - -### 2. 服务启动与初始化 - -#### 2.1 ``compose_init.sh``脚本需要填写的密码是什么? - -执行``compose_init.sh``提示需要输入的密码是数据库的初始化密码,默认为``TCA!@#2021`` - -```bash -$ ./compose_init.sh -Recreating tca_open_source_mysql_1 ... done -Recreating tca_open_source_redis_1 ... done -wait db [DB default password: TCA!@#2021] -Enter password: <此处输入'TCA!@#2021'> -``` - -#### 2.2 服务占用端口异常 - -TCA 本地部署启动后,会监听多个端口: - -- web服务:80 -- nginx服务:8000 -- main服务:8001 -- analysis服务:8002 -- login服务:8003 -- file-nginx服务:8004 -- file服务:8804 -- scmproxy服务:8009 - -如果出现端口占用冲突,建议采用以下方式解决: - -1. 调整其他程序监听的端口号,避免跟上述TCA服务的端口号出现冲突 -2. 采用Docker-Compose方式启动TCA,仅监听80端口 - -不推荐调整TCA指定服务的端口号,需要调整多处配置,以及可能会影响到后续服务的升级 - -#### 2.3 服务输出日志找不到 - -本地部署输出的日志位置: - -1. ``main``服务输出的日志目录:``server/projects/main/log`` - - 服务启动日志:``server/projects/main/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/main/log/gunicorn_access.log`` - - Celery Worker启动日志(处理异步任务):``server/projects/main/nohup_worker.out`` - - Celery Beat启动日志(启动定时任务):``server/projects/main/nohup_beat.out`` - - 服务运行日志:``server/projects/main/log/codedog.log`` - - Celery Worker运行日志:``server/projects/main/log/main_celery.log`` - - Celery Beat运行日志:``server/projects/main/log/main_beat.log`` -2. ``analysis``服务输出的日志目录:``server/projects/analysis/log`` - - 服务启动日志:``server/projects/analysis/log/gunicorn_error.log`` - - Celery Worker启动日志:``server/projects/analysis/nohup.out`` - - 服务接收请求日志:``server/projects/analysis/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/analysis/log/codedog.log`` - - Celery Worker运行日志(处理结果入库):``server/projects/analysis/log/celery.log`` -3. ``login``服务输出的日志目录:``server/projects/login/log`` - - 服务启动日志:``server/projects/login/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/login/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/login/log/codedog.log`` -4. ``file``服务输出的日志目录:``server/projects/file/log`` - - 服务启动日志:``server/projects/file/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/file/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/file/log/codedog_file.log`` -5. ``scmproxy``服务输出的日志目录:``server/projects/scmproxy/logs`` - - 服务启动日志:``server/projects/scmproxy/nohup.out`` - - 服务运行日志:``server/projects/scmproxy/logs/scmproxy.log`` - -### 3. 平台使用 - -#### 3.1 平台登录的默认账号密码是什么? - -默认账号: ``CodeDog``,密码: ``admin`` - -#### 3.2 平台默认的API Token是什么? - -默认Token是``0712b895f30c5e958ec71a7c22e1b1a2ad1d5c6b`` - -如果在平台上刷新了``CodeDog``用户的Token,需要将刷新后的Token填写到以下文件中: - -1. ``server/scripts/config.sh``文件 - - 更新``CODEDOG_TOKEN``、``FILE_SERVER_TOKEN``变量的值(3个位置) -2. ``server/dockerconfs/.env.local``文件 - - 更新``CODEDOG_TOKEN``、``FILE_SERVER_TOKEN``变量的值(3个位置) - -然后重启服务。 - -1. 本地部署: - - ```bash - cd server/ - ./scripts/deploy.sh start - ``` - -2. docker-compose部署: - - ```bash - $ docker-compose stop - # 稍等片刻 - $ docker-compose up -d - ``` - -#### 3.3 代码库登记出错,出现代码库及账号不匹配 - -该错误出现可能有以下几个原因: - -1. 账号密码不准确或登记的代码库地址不存在 -2. 登记``github``使用的密码需要使用[``personal access token``](https://github.com/settings/tokens) -3. scmproxy服务启动失败 - - 本地部署:执行``ps aux | grep proxyserver``看看是否有``python proxyserver.py``执行进程,如果不存在可以看一下``server/projects/scmproxy/nohup.out``看看启动失败的原因 - - docker-compose部署:在项目根目录执行``docker-compose ps``看看``scmproxy``容器是否正常启动,如果没有启动,可以执行``docker-compose logs scmproxy``看看启动失败的原因 -4. scmproxy所在的机器/容器因为网络问题无法访问对应的代码库 - - 可以手动在机器/容器中执行``git clone xxxx``(xxx表示待登记的代码库),检查看看是否能够正常拉取 -5. scmproxy所在的机器git版本较低,出现``unknown option `local` ``错误 - - 可以升级机器上的git版本,目前工具支持最低的git版本为``1.8.3.1`` - -#### 3.4 查看问题文件提示**获取代码信息耗时较久,请稍后再试** - -出现该提示的原因是,代码库偏大或``clone``代码库时间较长,可以稍等一会再刷新重试 - -#### 3.5 客户端访问文件服务器,提示``method(upload_file) call fails on error: Expecting value: line 1 column 1 (char 0)`` - -出现这种错误,可能是本地配置异常或token配置有问题,检查方式如下: - -1. 检查客户端的``config.ini``文件配置的URL是否为当前Server部署的地址:(xxx需要调整为实际的路径) - - ```bash - [SERVER_URL] - URL=http://xxx/server/main/ - [FILE_SERVER] - URL=http:/xxx/server/files/ - ``` - - 如果xxx不一致需要调整为一致 - > 注: xxx地址与在浏览器访问平台的xxx地址是一致的,不需要区分端口 -2. 检查客户端访问Server是否能通: - - ```bash - curl -v http://xxx/server/main/ - ``` - - 如果不通,则需要检查客户端机器访问Server机器是否有网络限制 -3. 检查当前在``codedog.ini``-``[config]token``与``config.ini``文件配置的``[FILE_SERVER]TOKEN``是否一致,如果不一致需要调整为一致 -4. 检查用户``CodeDog``的``Token``是否被刷新了然后没有更新到配置文件中 - -#### 3.6 客户端访问文件服务器,提示``Connection timed out`` - -本地客户端执行过程提示``method (upload file) call fails on error: `` 该如何处理? -一般情况下,这个问题是客户端与Server之间网络不通导致,可以检查一下是否有防火墙限制或者配置的URL是内部IP或地址,可以通过以下方式检查 - -1. 检查客户端的``config.ini``文件配置的URL是否为当前Server部署的地址:(xxx需要调整为实际的路径) - - ```bash - [SERVER_URL] - URL=http://xxx/server/main/ - [FILE_SERVER] - URL=http:/xxx/server/files/ - ``` - -2. 检查客户端访问Server是否能通: - - ```bash - curl -v http://xxx/server/main/ - ``` - - 如果不通,则需要检查客户端机器访问Server机器是否有网络限制 - -#### 3.7 任务执行结果异常,提示**第三方依赖文件服务器异常** - -出现该错误提示,一般是访问文件器出错或文件服务器本身有问题,可以通过以下方式检查: -需要检查``analysis-worker``的日志(本地部署:``server/projects/analysis/log/celery.log``,docker-compose部署:``docker-compose exec analysis-worker /bin/bash``进入容器后访问``log/celery.log``查看具体错误原因 - -如果提示``no route to host``可能是当前机器/容器无法访问当前宿主机的IP,可以检查一下当前防火墙的设置,是否限制了``analysis-worker``来源的访问 - -#### 3.8 客户端执行时提示**工具(xxx)扫描进程为空,请联系管理员配置工具进程!** - -出现该错误提示,一般是Server未进行初始化,可以通过执行以下命令初始化后再启动测试 - -- 本地部署:``cd server && ./scripts/deploy.sh init`` -- docker-compose部署:``./compose_init.sh`` - -## CodeAnalysis仓库文件问题 - -### 1. clone到本地时相关md文件内资源图片无法显示 - -为防止国内用户访问CodeAnalysis Github首页时图片资源加载失败,目前各个md文件中的图片资源引用地址调整增加了URL前缀`https://tencent.github.io/CodeAnalysis/`。 - -用户下载代码库到本地后,发现无法访问资源文件时,请检查本地网络是否能够连通外网,如果无法连通外网,可以在文档引入资源地址中进行**相对路径**替换,调整各个资源文件的链接。 - -- 对于根目录下的md文件,直接删除URL前缀即可: - - 例如在`https://tencent.github.io/CodeAnalysis/media/homepage.png`这个链接可以调整为`media/homepage.png` - -- 对于其他目录下的md文件,删除URL前缀后,需调整文件相对路径链接: - - 例如对于`doc/client.md`, 需将`https://tencent.github.io/CodeAnalysis/media/clientConfigIni.png`这个链接调整为`../media/clientConfigIni.png` diff --git a/web/packages/tca-document/en/quickStarted/codeDeploy.md b/web/packages/tca-document/en/quickStarted/codeDeploy.md deleted file mode 100644 index 95cd0ae1c..000000000 --- a/web/packages/tca-document/en/quickStarted/codeDeploy.md +++ /dev/null @@ -1,90 +0,0 @@ -# 源码部署 -兼容旧版的部署方式 -#### 依赖环境 - -- 系统环境 - - Linux - - 最低配置:2核4G内存、100G硬盘存储空间 - -- 环境准备 -> 目前TCA脚本已封装好Python、Mariadb、Redis与Nginx安装步骤,可以按“操作说明”内容进行操作 - - - **Python 3.7**,[安装指引](./references/install_python37_on_centos.md) - - - **MySQL服务(MySQL5.7.8以上版本或Mariadb 10.5以上版本)**,[安装指引](./references/install_mysql_on_centos.md) - - - **Redis服务(4.0版本以上)**,[安装指引](./references/install_redis_on_centos.md) - - - **Nginx服务** - - :::warning - 仅适用于本地部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 - ::: - -- 权限准备 - - - 环境权限:安装 Server 依赖软件(python、nginx、yum 等软件包)需要使用 ROOT 权限 - - 启动 Server服务时可以使用非 ROOT 用户运行 - - 数据库权限:Server 服务执行数据库初始化需要依赖 ``CREATE、ALTER、INDEX、DELETE、LOCK TABLES、SELECT、INSERT、REFERENCES、UPDATE`` 权限 -- 端口使用:需要开放80端口的访问权限(80为TCA平台默认访问端口),或调整 Web 服务默认的访问端口地址 - -#### 操作说明 - -##### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 安装基础软件与部署TCA(可根据脚本选项确定是否要安装相关基础软件),执行 - ```bash - $ bash ./quick_install.sh local deploy - ``` - 执行该命令会做以下事情: - - 检测本地Python3.7、Mariadb/MySQL、Redis与Nginx,如果不存在会提示安装(install) - - 部署TCA Server、Web与Client,并进行初始化(install) - - 启动TCA Server、Web与Client(start) - - 检测TCA的运行状态(check) - - >注:在运行过程中,脚本会检测本地是否安装了相关基础软件(Python3.7、MySQL/Mariadb、Redis、Nignx),如果未安装会输出以下类似提示语: - >``` - >Do you want to install [Redis] by this script? - >Please enter:[Y/N] - >``` - >如果确定通过脚本安装可以输入`Y`。 -3. 执行完成,无其他报错,即可登录: - - TCA 平台初始登录账号是``CodeDog``,密码是``admin``, - -##### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `bash ./quick_install.sh local install tca`:更新相关配置 - - `bash ./quick_install.sh local start`:启动服务(会自动关闭之前的服务) - - `bash ./quick_install.sh local check`:检查服务是否启动失败 - -注: -1. `local install`命令行参数说明: - - `base`:安装Python、Mariadb/MySQL、Redis与Nginx - - `tca`:初始化或更新TCA Server、Web、Client相关配置和数据 - - `server`:初始化或更新TCA Server相关配置和数据 - - `web`:初始化或更新TCA Web相关配置和数据 - - `client`:初始化或更新TCA Client相关配置和数据 - - 不填参数,默认会执行`base`、`tca`相关操作 - -##### 启动和停止服务 - -- 启动所有服务:`bash ./quick_install.sh local start` -- 启动Main相关服务:`bash ./quick_install.sh local start main` - - `local start`支持启动指定服务,如上述的启动Main服务,还支持`mysql/redis/analysis/file/login/scmproxy/nginx/client/all` -- 停止所有服务:`.bash /quick_install.sh local stop` -- 停止Main相关服务:`bash ./quick_install.sh local stop main` - - `local stop`支持停止指定服务,如上述的停止Main服务,还支持`analysis/file/login/scmproxy/nginx/client/all` - -注: -1. 启动时会自动关闭之前已经运行的服务 -2. `local start`支持启动指定服务,如上述的启动Main服务,还支持`mysql/redis/main/analysis/file/login/scmproxy/nginx/all` - - `mysql`和`redis`默认会使用`systemctl`进行启动,如果`systemctl`无法使用,则会直接使用`nohup`方式运行相关服务 - -##### 检查服务运行状态 -检查服务运行状态:`bash ./quick_install.sh local check` - - 目前支持检查server与web,暂不支持client - -##### 获取服务输出日志 -打印TCA Server各个服务的日志路径: `bash ./quick_install.sh local log` \ No newline at end of file diff --git a/web/packages/tca-document/en/quickStarted/deployClient.md b/web/packages/tca-document/en/quickStarted/deployClient.md deleted file mode 100644 index 723dd738e..000000000 --- a/web/packages/tca-document/en/quickStarted/deployClient.md +++ /dev/null @@ -1,182 +0,0 @@ -# 部署与配置客户端 - -## 通过源代码 - -### 依赖环境 - -- 系统环境 - - - Linux,Windows或macOS - -- 环境准备 - - - **Python 3.7**,[安装指引](./references/install_python37_on_centos.md) - -### 使用步骤 - -#### 安装第三方库 - -```bash -# 源码根目录下执行 -pip3 install -r client/requirements/app_reqs.pip -``` - -#### 安装第三方工具 - -```bash -# 源码根目录 -cd client/requirements - -# 执行安装脚本 -# Linux/macOS环境 -./install.sh -# Windows环境 -./install.bat -``` - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - - 将 `` 替换成实际的serve ip(可包含端口号)。 - - ![客户端执行环境配置](https://tencent.github.io/CodeAnalysis/media/clientConfigIni.png) - -- 配置 `client/codedog.ini` 文件 - - 必填项:`token`、`org_sid`、`team_name`、`source_dir` - - - **个人令牌** - `token`:从 TCA 页面获取,前往[个人中心]-[个人令牌]-复制Token - - ![personalToken](../../images/personalToken.png) - - - **团队编号** - `org_sid`:进入 TCA 项目概览页,从 URL 中获取 - - - **项目名称** - `team_name`::进入 TCA 项目概览页,从 URL 中获取 - - :::tip - 项目概览URL格式:`http://{域名}/t/{org_sid}/p/{team_name}/profile` - ::: - - - **分析路径** - `source_dir`: 本地代码目录路径 - - :::tip - - 如果项目代码为编译型语言(比如:C/C++,C#,Go,Java,Kotlin,Objective-C等),且使用的分析方案中配置了编译型工具(如图,使用了OC推荐规则包),需要填写`build_cmd`编译命令。 - - - 其他可选项按需填写,不填写时按默认配置执行 - ::: - -#### 启动客户端 - -```bash -# 源码根目录 -cd client - -# 执行客户端脚本 -python3 codepuppy.py localscan -``` - -:::warning -Client 的实现及启动脚本均依赖 Python3 版本为 3.7,可执行 ``python3 --version`` 查看版本。若版本有误,可安装版本为3.7的python并软链接到python3命令。 -::: - -:::tip - -- `codedog.ini` 各项参数可由命令行传入,获取详细参数说明可运行 `python3 codepuppy.py localscan -h` - -- 使用`localscan`命令启动本地单次的代码分析,如需启动分布式并行分析任务,请参考[使用分布式节点模式](../client/README.md#五使用分布式节点模式执行客户端)进行配置。 -::: - -## 通过Docker-Compose - -:::tip -适用于快速上手体验。使用docker运行,可以免去客户端环境依赖的安装,避免环境兼容性问题。 - -但是由于环境受限于docker,会无法复用本地的编译环境,部分需要编译的工具无法使用。 -::: - -### 使用步骤 - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - -- 配置 `client/codedog.ini` 文件 - -:::tip -同通过源代码使用-[配置客户端](./deployClient.md#配置客户端) -::: - -#### 构建镜像 - -1. 安装Docker,安装教程:[官方文档](https://docs.docker.com/engine/install/) - -2. 安装Docker-Compose,安装教程:[官方文档](https://docs.docker.com/compose/install/) - -3. 进入`client`目录,构建docker镜像 - -```bash -docker build -t tca-client . -``` - -#### 启动客户端 - -##### 方案一:直接使用docker运行 - -进入`client`目录,执行以下命令 - -```bash -# 按照实际情况填写`SOURCE_DIR`环境变量值 -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -##### 方案二:使用docker内bash终端运行 - -1. 进入docker容器内的bash终端 - - ```bash - # 按照实际情况填写`SOURCE_DIR`环境变量值 - export SOURCE_DIR=需要扫描的代码目录绝对路径 - docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash - ``` - -2. 通过命令行启动client代码 - - ```bash - python3 codepuppy.py localscan - ``` - -## 通过可执行文件 - -### 依赖环境 - -- 系统环境 - - - Linux,Windows或macOS - -### 使用步骤 - -#### 下载客户端 - -1. 从[发布页面](https://github.com/Tencent/CodeAnalysis/releases)下载与系统相对应的客户端压缩包到本地。 - -2. 解压缩。 - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - -- 配置 `client/codedog.ini` 文件 - -:::tip -同通过源代码使用-[配置客户端](./deployClient.md#配置客户端) -::: - -#### 启动客户端 - -进入到`client`目录下,执行客户端 - -```bash -./codepuppy localscan -``` diff --git a/web/packages/tca-document/en/quickStarted/deploySever.md b/web/packages/tca-document/en/quickStarted/deploySever.md deleted file mode 100644 index 7ee1a6e54..000000000 --- a/web/packages/tca-document/en/quickStarted/deploySever.md +++ /dev/null @@ -1,130 +0,0 @@ -# 部署 TCA -TCA提供部署脚本,支持一键式快速部署Server、Web、Client。 -脚本共提供三种部署方式:Docker部署(推荐)、[Docker-Compose部署](./dockercomposeDeploy.md)、[源码部署](./codeDeploy.md),可根据您的具体使用场景任意选择其一进行部署。 - -## Docker快速部署 - -:::warning -仅适用于Docker部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 -::: - -### 依赖环境 - -- 系统环境 - - Linux、macOS、Windows - - 最低配置:2核4G内存、100G硬盘存储空间 -- 环境准备 - - Docker -- 权限准备 - - 需要开放80、8000端口的访问权限(80为TCA平台访问端口,8000为TCA Server访问端口) - -### 部署对象 -Server、Web 与 Client - -### 操作说明 -#### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 执行命令: - ```bash - bash ./quick_install.sh docker deploy - ``` -::: tip -通过Docker部署默认会在当前根目录下的挂载三个路径: -- `.docker_temp/logs`:容器内的`/var/log/tca/`,存放TCA平台的日输出文件; -- `.docker_temp/data`:容器内的`/var/opt/tca/`, 存放TCA平台的服务数据,主要是Mariadb、Redis; -- `.docker_temp/configs`:容器内的``/etc/tca``,存放TCA平台的配置文件,主要是`config.sh` -::: - -#### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `TCA_IMAGE_BUILD=true ./quick_install.sh docker deploy`:重新构建并启动tca容器 -::: tip -`TCA_IMAGE_BUILD=true`表示从本地构建TCA镜像运行 -::: - -#### 运行容器 -如果已经在机器上执行过``docker deploy``,并保留容器数据的,可以执行以下命令启动容器,继续运行TCA - -```bash -bash ./quick_install.sh docker start -``` - -#### 停止容器 -如果容器正在运行,希望停止容器,可以运行 - -```bash -bash ./quick_install.sh docker stop -``` - -# 使用TCA -成功部署TCA后,请开始您的代码分析。 -## 进入平台页面 - -在浏览器输入`http://部署机器IP/`,点击立即体验,完成登录后即可跳转到团队列表页 - -:::tip -默认平台登录账号/密码:CodeDog/admin - -如部署过程中,已调整默认账号密码,请按照调整后的账号密码进行登录 -::: - -## 创建团队及项目 - -- 完成团队创建 - -- 完成项目创建 - -## 登记代码库 - -登记代码库,输入代码库地址以及凭证信息等,完成代码库登记。 - -![registerCodeRepo](../../images/registerCodeRepo.png) - -## 创建分析项目 - -![开始分析](../../images/start_scan_02.png) - -::: tip -1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 -2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目。 -::: - -### 分析方案说明 - -- 分析方案是用于对代码库进行分析的一套配置集合。 - -- 更多分析方案配置可查阅[帮助文档-分析方案](../guide/分析方案/基础属性配置.md) - -![creataAnalysePlan](../../images/creataAnalysePlan.png) - -::: tip -本次部署会默认启动运行环境为「Codedog_Linux」的客户端,若需扩展更多运行环境,详见客户端[常驻节点分析](../guide/客户端/常驻节点分析.md) -::: - -![planPage](../../images/planPage.png) - -## 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../images/start_scan_06.png) - -::: tip -- TCA推荐使用`在线分析`,您可根据具体使用场景选择其一。 -- `在线分析`表示配置代码库链接后,TCA客户端拉取代码后进行分析;`客户端分析`在配置本地待扫描代码路径后,无需代码拉取直接分析本地代码。 -- `在线分析`与`客户端分析`具体详情及配置参考[TCA客户端配置详情](../guide/客户端/配置详情.md) -::: - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../guide/代码检查/分析结果查看.md) 等。 - -![分支概览](../../images/start_scan_04.png) \ No newline at end of file diff --git a/web/packages/tca-document/en/quickStarted/dockercomposeDeploy.md b/web/packages/tca-document/en/quickStarted/dockercomposeDeploy.md deleted file mode 100644 index e9062bb65..000000000 --- a/web/packages/tca-document/en/quickStarted/dockercomposeDeploy.md +++ /dev/null @@ -1,49 +0,0 @@ -# Docker-Compose快速部署 -#### 部署对象 -Server、Web 与 Client - -:::warning -仅适用于Docker-Compose部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 -兼容之前的部署方式 -::: - -#### 操作说明 -##### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 执行命令: - - `bash ./quick_install.sh docker-compose deploy`:启动tca_server容器 - -注意:通过Docker-Compose部署默认会在当前根目录下的挂载三个路径: - -- `.docker_data/logs`:存放TCA平台的各个服务日志输出目录; -- `.docker_data/mysql`:存放TCA平台的MySQL数据 -- `.docker_data/redis`:存放TCA平台的Redis数据 -- `.docker_data/filedata`:存放TCA平台文件服务器的文件 - -##### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `bash ./quick_install.sh docker-compose build`:重新构建TCA相关镜像 - - `bash ./quick_install.sh docker-compose deploy`: 重新部署TCA相关容器与初始化(或刷新数据) - -##### 运行操作 -如果已经在机器上执行过``docker-compose deploy``,并保留容器数据的,可以执行以下命令启动容器,继续运行TCA - -```bash -bash ./quick_install.sh docker-compose start -``` - -##### 停止操作 -如果容器正在运行,希望停止容器,可以执行以下命令 - -```bash -bash ./quick_install.sh docker-compose stop -``` - -##### 构建镜像操作 -如果希望构建镜像,可以执行以下命令 - -``` -bash ./quick_install.sh docker-compose build -``` \ No newline at end of file diff --git a/web/packages/tca-document/en/quickStarted/initRepo.md b/web/packages/tca-document/en/quickStarted/initRepo.md deleted file mode 100644 index f96467f0f..000000000 --- a/web/packages/tca-document/en/quickStarted/initRepo.md +++ /dev/null @@ -1,45 +0,0 @@ -# 创建代码分析项目 - -成功部署并启动 Server 与 Web 服务后,通过以下步骤创建您的第一个代码分析项目。 - -## 进入平台页面 - -在浏览器输入`http://部署机器IP/`,点击立即体验,完成登录后即可跳转到团队列表页 - -:::tip -默认平台登录账号/密码:CodeDog/admin - -如部署过程中,已调整默认账号密码,请按照调整后的账号密码进行登录 -::: - -## 创建团队及项目 - -- 完成团队创建 - -- 完成项目创建 - -## 登记代码库 - -登记代码库,输入代码库地址以及凭证信息等,完成代码库登记。 - -![registerCodeRepo](../../images/registerCodeRepo.png) - -## 创建分析项目 - -![开始分析](../../images/start_scan_02.png) - -::: tip - -1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 -2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目。 -::: - -### 分析方案说明 - -- 分析方案是用于对代码库进行分析的一套配置集合。 - -- 更多分析方案配置可查阅[帮助文档-分析方案](../guide/分析方案/基础属性配置.md) - -![creataAnalysePlan](../../images/creataAnalysePlan.png) - -![planPage](../../images/planPage.png) diff --git a/web/packages/tca-document/en/quickStarted/intro.md b/web/packages/tca-document/en/quickStarted/intro.md deleted file mode 100644 index 055ce7737..000000000 --- a/web/packages/tca-document/en/quickStarted/intro.md +++ /dev/null @@ -1,36 +0,0 @@ -# 平台概述 - -**腾讯云代码分析**(Tencent Cloud Code Analysis,简称TCA,内部曾用研发代号 **CodeDog** )是集众多分析工具的云原生、分布式、高性能的代码综合分析跟踪平台,包含服务端、Web端和客户端三个组件,已集成一批自研工具,同时也支持动态集成业界各编程语言的分析工具。 - -### 使用TCA Action快速体验 -使用TCA Action,只需要在代码仓库中添加`.github/workflows/tca.yml`文件,就可以直接在GitHub工作流中快速体验代码分析。请参考:[TCA-action指引](https://github.com/TCATools/TCA-action/blob/main/README.md) - -### 部署TCA - -拉取 [代码库](https://github.com/Tencent/CodeAnalysis) 后,您可以通过以下三种方式部署腾讯云代码分析平台: - -- [通过 Docker 部署](./deploySever.md#通过docker) - -- [通过源代码](./codeDeploy.md#通过源代码) - -- [通过 Docker-Compose 部署](./dockercomposeDeploy.md#通过docker-compose) - -### 创建首个代码分析项目 - -成功部署并启动TCA后,您可以按照 [指引](./deploySever.md) 创建您的首个代码分析项目。 - -:::tip -默认平台登录账号/密码:CodeDog/admin -::: - -### 快速扩展客户端 - -TCA客户端支持通过可执行文件进行快速扩展部署,详见[通过可执行文件](./deployClient.md#通过可执行文件) - -:::tip -客户端可在本地执行代码分析,也可以作为[在线常驻节点](../advanced/任务分布式执行.md)进行在线分析。 -::: - -### 了解更多 - -更多关于腾讯云代码分析平台的使用指南和配置说明,参见[帮助文档](../guide/README.md)。 diff --git a/web/packages/tca-document/en/quickStarted/references/install_mysql_on_centos.md b/web/packages/tca-document/en/quickStarted/references/install_mysql_on_centos.md deleted file mode 100644 index 0337b5cfc..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_mysql_on_centos.md +++ /dev/null @@ -1,102 +0,0 @@ -# 在 CentOS 安装 MySQL - -## 注意 - -本文档仅供参考,不适用于正式环境部署,正式环境建议使用专业的MySQL服务(比如[腾讯云的MySQL产品](https://cloud.tencent.com/product/cdb)) - -## 环境 - -CentOS 7.3 版本 - -## 安装 mysql yum源 - -```bash -wget https://repo.mysql.com//mysql57-community-release-el7-11.noarch.rpm -yum localinstall mysql57-community-release-el7-11.noarch.rpm -``` - -安装成功后,查看MySQL版本: - -```bash -yum repolist all | grep mysql -``` - -输出结果: - -```bash -mysql-cluster-7.5-community/x86_64 MySQL Cluster 7.5 Community 禁用 -mysql-cluster-7.5-community-source MySQL Cluster 7.5 Community - 禁用 -mysql-cluster-7.6-community/x86_64 MySQL Cluster 7.6 Community 禁用 -mysql-cluster-7.6-community-source MySQL Cluster 7.6 Community - 禁用 -!mysql-connectors-community/x86_64 MySQL Connectors Community 启用: 221 -mysql-connectors-community-source MySQL Connectors Community - S 禁用 -!mysql-tools-community/x86_64 MySQL Tools Community 启用: 135 -mysql-tools-community-source MySQL Tools Community - Source 禁用 -mysql-tools-preview/x86_64 MySQL Tools Preview 禁用 -mysql-tools-preview-source MySQL Tools Preview - Source 禁用 -mysql55-community/x86_64 MySQL 5.5 Community Server 禁用 -mysql55-community-source MySQL 5.5 Community Server - S 禁用 -mysql56-community/x86_64 MySQL 5.6 Community Server 禁用 -mysql56-community-source MySQL 5.6 Community Server - S 禁用 -!mysql57-community/x86_64 MySQL 5.7 Community Server 启用: 544 -mysql57-community-source MySQL 5.7 Community Server - S 禁用 -mysql80-community/x86_64 MySQL 8.0 Community Server 禁用 -mysql80-community-source MySQL 8.0 Community Server - S 禁用 -``` - -## 安装MySQL - -```bash -yum install mysql-community-server -``` - ->1.如遇以下报错,可尝试运行`yum install mysql-community-server --nogpgcheck`安装 -> Public key for mysql-community-libs-compat-5.7.37-1.el7.x86_64.rpm is not installed -> Failing package is: mysql-community-libs-compat-5.7.37-1.el7.x86_64 -> GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql ->2.如遇以下报错,可执行`yum module disable mysql`后重试安装 ->All matches were filtered out by modular filtering for argument: mysql-community-serve ->Error: Unable to find a match: mysql-community-server - -## 配置MySQL服务 - -安装好的MySQL配置文件路径是``/etc/my.cnf``,这里可以根据需要调整,比如可以调整: - -- datadir:MySQL存放数据的路径,如果有额外挂载磁盘,可以考虑指向相关路径 - -## 启动MySQL服务 - -```bash -systemctl start mysqld -``` - -确认MySQL正常启动 - -```bash -systemctl status mysqld -``` - -查看生成 MySQL root用户临时密码: - -```bash -grep 'temporary password' /var/log/mysqld.log -``` - -### 修改root用户密码 - -连接MySQL服务 - -```bash -$ mysql -uroot -p -# 输出上述查询到的临时密码 -``` - -修改root用户的密码(下面是改成 ``Password@2021``,这里根据自行需要进行调整): - -```SQL -ALTER USER 'root'@'localhost' IDENTIFIED BY 'Password@2021'; -``` - -## 参考文档 - -- [Installing MySQL on Linux Using the MySQL Yum Repository](https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html) diff --git a/web/packages/tca-document/en/quickStarted/references/install_nginx_from_source.md b/web/packages/tca-document/en/quickStarted/references/install_nginx_from_source.md deleted file mode 100644 index ca924bf4a..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_nginx_from_source.md +++ /dev/null @@ -1,136 +0,0 @@ -# 源码安装 Nginx - -## 运行环境 - -1. 基于x86_64的CentOS -2. 基于aarch64(鲲鹏920)的UOS V20 -3. 基于aarch64(飞腾2000)的TencentOS Server - -## 环境准备 - -安装编译打包需要的工具 - -```bash -yum -y install gcc zlib-devel pcre-devel bzip2-devel openssl-devel readline-devel -``` -> Ubuntu: ``apt install gcc libssl-dev zlib1g-dev libpcre3-dev libbz2-dev libreadline-dev`` - -## 下载源码 - -```bash -wget http://nginx.org/download/nginx-1.20.2.tar.gz -``` - -## 解压安装 - -```bash -# 解压 -$ tar zvxf nginx-1.20.2.tar.gz -C /usr/local/src - -# 进入源码目录 -$ cd /usr/local/src/nginx-1.20.2 - -# 配置 -$ ./configure \ ---sbin-path=/usr/local/nginx/nginx \ ---conf-path=/etc/nginx/nginx.conf \ ---pid-path=/run/nginx.pid \ ---with-stream \ ---with-http_ssl_module --with-http_v2_module --with-http_auth_request_module - -# 构建nginx -$ make -j4 -$ make install -$ make clean - -# 建立软链 -$ ln -s /usr/local/nginx/nginx /usr/local/bin/nginx -``` - -## 添加nginx配置文件 - -```bash -mkdir /etc/nginx/conf.d/ -vi /etc/nginx/nginx.conf -``` - -检查``nginx.conf``配置文件: - -1. 检查``pid /run/nginx.pid``,如果缺失或被注释则加上,加上位置如下所示: -2. 检查是否缺失这一行``include conf.d/*.conf;``,如果缺失则加上,加上位置如下所示: - -```bash -# ...省略内容 -#pid logs/nginx.pid; # 默认有的 -pid /run/nginx.pid; - -events { - # ...省略内容 -} - -# ...省略内容 - -http { - # ...省略内容 - # - include conf.d/*.conf; - server { - # ...省略内容 - } -} - -``` - -后续可以将nginx配置文件放置到``/etc/nginx/conf.d/``目录下 - - - -## 配置开机自动启动 - -```bash -vim /usr/lib/systemd/system/nginx.service -``` - -输入以下内容: - -```bash -[Unit] -Description=The nginx HTTP and reverse proxy server -After=network-online.target remote-fs.target nss-lookup.target -Wants=network-online.target - -[Service] -Type=forking -PIDFile=/run/nginx.pid -# Nginx will fail to start if /run/nginx.pid already exists but has the wrong -# SELinux context. This might happen when running `nginx -t` from the cmdline. -# https://bugzilla.redhat.com/show_bug.cgi?id=1268621 -ExecStartPre=/bin/rm -f /run/nginx.pid -ExecStartPre=/usr/local/bin/nginx -t -ExecStart=/usr/local/bin/nginx -ExecReload=/usr/local/bin/nginx -s reload -ExecStop=/usr/local/bin/nginx -s stop -KillSignal=SIGQUIT -TimeoutStopSec=5 -KillMode=process -PrivateTmp=true - -[Install] -WantedBy=multi-user.target -``` - -启动nginx: - -```bash -systemctl start nginx -``` - -开机自动启动nginx: - -```bash -systemctl enable nginx -``` - -## 参考文档 - -- [Nginx官方文档](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#downloading-the-sources) diff --git a/web/packages/tca-document/en/quickStarted/references/install_python37_on_centos.md b/web/packages/tca-document/en/quickStarted/references/install_python37_on_centos.md deleted file mode 100644 index ac782a828..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_python37_on_centos.md +++ /dev/null @@ -1,109 +0,0 @@ -# 在 CentOS 安装 Python3.7 - -## 下载Python源码包 - -```bash -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz -``` - -## 安装前准备 - -安装依赖组件 - -```bash -yum -y install wget zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel xz-devel -``` - -## 解压安装 - -```bash -# 解压到/usr/local/src目录 -$ tar zvxf Python-3.7.12.tgz -C /usr/local/src -$ cd /usr/local/src/Python-3.7.12 -# 编译前配置 -$ ./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -$ make -j8 -# 安装Python -$ make install -# 清理编译产出的中间文件 -$ make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -$ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -$ ldconfig -``` - -## 检查 - -检查Python版本是否安装成功 - -```bash -$ python --version -Python 3.7.12 # 正常输出,表示安装成功 -``` - -注: - -1. 链接到/usr/local/bin/目录不会影响系统软件(比如yum)的使用,因为 yum 工具指定的Python路径是``/usr/bin/python`` -2. 一般情况下,PATH配置是先``/usr/local/bin``再``/usr/bin`` -3. 检查``python -v``输出结果是否为``Python 3.7.12``版本,如果不是该版本,可能影响后续依赖安装和服务运行 - -## pypi下载源配置 - -pip默认是到``pypi``官方源下载第三方依赖包,下载速度可能会比较慢,可以考虑调整为腾讯云的``pypi``下载源,调整方式: - -```bash -mkdir ~/.pip/ -echo "extra-index-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` - -## 一键安装脚本 -以下脚本内容是上面的步骤集合,省去了复制粘贴的重复动作。 -1. 创建文件 `install_py37.sh`,写入以下 shell 脚本 -2. 赋予执行权限,`chmox +x install_py37.sh` -3. 执行脚本,`./install_py37.sh` - -```bash -#!/bin/env bash - -## 下载 Python 源码,如果已下载源码在脚本当前目录下,可注释跳过下载步骤 -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz - -## 安装编译依赖组件 -yum -y install wget zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel xz-devel - -## 解压安装 -# 解压到/usr/local/src目录 -tar zvxf Python-3.7.12.tgz -C /usr/local/src -cd /usr/local/src/Python-3.7.12 -# 编译前配置 -./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -make -j8 -# 安装Python -make install -# 清理编译产出的中间文件 -make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -ldconfig - -## 检查Python版本是否安装成功 -echo -e "\033[1;42;37m[$(date "+%Y/%m/%d %H:%M:%S")] [Check]: 检查Python版本\033[0m" -python --version -echo -e "\033[1;42;37m[$(date "+%Y/%m/%d %H:%M:%S")] [Check]: 检查Python版本\033[0m" - -## pypi下载源配置 -mkdir ~/.pip/ -echo "extra-index-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` diff --git a/web/packages/tca-document/en/quickStarted/references/install_python37_on_ubuntu.md b/web/packages/tca-document/en/quickStarted/references/install_python37_on_ubuntu.md deleted file mode 100644 index 14459aaf1..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_python37_on_ubuntu.md +++ /dev/null @@ -1,66 +0,0 @@ -# 在 Ubuntu 安装 Python3.7 - -> 注:当前Ubuntu版本为18.04 - -## 下载Python源码包 - -```bash -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz -``` - -## 安装前准备 - -安装依赖组件 - -```bash -apt-get update -apt-get install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev libffi-dev wget libbz2-dev tk-dev gcc make -``` - -## 解压安装 - -```bash -# 解压到/usr/local/src目录 -$ tar zvxf Python-3.7.12.tgz -C /usr/local/src -$ cd /usr/local/src/Python-3.7.12 -# 编译前配置 -$ ./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -$ make -j8 -# 安装Python -$ make install -# 清理编译产出的中间文件 -$ make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -$ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -$ ldconfig -``` - -## 检查 - -检查Python版本是否安装成功 - -```bash -$ python --version -Python 3.7.12 # 正常输出,表示安装成功 -``` - -注: - -1. 链接到/usr/local/bin/目录不会影响系统软件 -2. 一般情况下,PATH配置是先``/usr/local/bin``再``/usr/bin`` -3. 检查``python -v``输出结果是否为``Python 3.7.12``版本,如果不是该版本,可能影响后续依赖安装和服务运行 - -## pypi下载源配置 - -pip默认是到``pypi``官方源下载第三方依赖包,下载速度可能会比较慢,可以考虑调整为腾讯云的``pypi``下载源,调整方式: - -```bash -mkdir ~/.pip/ -echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` diff --git a/web/packages/tca-document/en/quickStarted/references/install_redis_from_source.md b/web/packages/tca-document/en/quickStarted/references/install_redis_from_source.md deleted file mode 100644 index 3ad90db98..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_redis_from_source.md +++ /dev/null @@ -1,107 +0,0 @@ -# 源码安装 Redis - -## 运行环境 - -1. 基于x86_64的CentOS -2. 基于鲲鹏920(aarch64)的UOS V20 -3. 基于飞腾2000(aarch64)的TencentOS Server - -## 环境准备 - -安装编译打包需要的工具 - -```bash -yum install -y gcc make tcl wget -``` - -## 下载源码 - -```bash -wget http://download.redis.io/releases/redis-5.0.4.tar.gz -``` - -## 编译安装 - -```bash -# 解压 -$ tar zvxf redis-5.0.4.tar.gz -C /usr/local/src - -# 进入源码目录 -$ cd /usr/local/src/redis-5.0.4 - -# 构建redis依赖库 -$ cd deps; make -j4 hiredis jemalloc linenoise lua -$ cd .. - -# 构建redis -$ make -j4 -$ make install -$ make clean -``` - -安装后,可以在``/usr/local/src/redis-5.0.4/src``目录和``/usr/local/bin/``目录下找到``redis-server``与``redis-cli``两个文件 - -## 调整配置 - -```bash -cp /usr/local/src/redis/redis.conf /etc/redis.conf -vim /usr/local/src/redis/redis.conf -``` - -```bash -# 设置Redis密码 -requirepass 123456 - -# 将 daemonize no 调整为 daemonize yes,将redis-server调整为默认后台启动 -daemonize yes - -# 配置日志 -logfile '/var/log/redis/redis-server.log' -``` - -## 启动服务 - -```bash -redis-server /etc/redis.conf -``` - -## 配置开机自动启动 - -```bash -vim /etc/systemd/system/redis.service -``` - -输入以下内容: - -```service -[Unit] -Description=redis-server -After=network.target - -[Service] -Type=forking -ExecStart=/usr/local/bin/redis-server /etc/redis.conf -ExecStop=/usr/local/bin/redis-cli shutdown -Restart=always - -PrivateTmp=true - -[Install] -WantedBy=multi-user.target -``` - -启动redis-server: - -```bash -systemctl start redis -``` - -开机自动启动redis: - -```bash -systemctl enable redis -``` - -## 参考文档 - -- [Redis官方文档](https://redis.io/topics/quickstart) diff --git a/web/packages/tca-document/en/quickStarted/references/install_redis_on_centos.md b/web/packages/tca-document/en/quickStarted/references/install_redis_on_centos.md deleted file mode 100644 index 1a10cf9be..000000000 --- a/web/packages/tca-document/en/quickStarted/references/install_redis_on_centos.md +++ /dev/null @@ -1,48 +0,0 @@ -# 在 CentOS 安装 Redis - -## 注意 - -本文档仅供参考,不适用于正式环境部署,正式环境建议使用专业的Redis服务(比如[腾讯云的Redis产品](https://cloud.tencent.com/product/crs)) - -## 环境 - -CentOS 7.3 版本 - -## yum 安装 redis - -```bash -yum install redis -``` - -注:安装redis可能会出现"no package redis available"的错误提示,请执行``yum install epel-release``后重试redis安装命令。 - -## 修改redis密码 - -```bash -$ vi /etc/redis.conf - -# 找到 requirepass foobared -# 复制一行并根据自己需要调整密码,比如 -requirepass tca123 -``` - -## 启动redis - -```bash -systemctl start redis -``` - -查看redis运行状态 - -```bash -systemctl status redis -``` - -## 访问redis - -```bash -$ redis-cli - -127.0.0.1:6379> auth tca123 -OK # 鉴权通过 -``` diff --git a/web/packages/tca-document/en/quickStarted/runProject.md b/web/packages/tca-document/en/quickStarted/runProject.md deleted file mode 100644 index 3fa362da5..000000000 --- a/web/packages/tca-document/en/quickStarted/runProject.md +++ /dev/null @@ -1,26 +0,0 @@ -# 启动代码分析 - -在完成 Server、Web 和 Client 相关部署和配置后,可通过平台执行代码分析。 - -## 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../images/start_scan_06.png) - -注: -- TCA推荐使用`在线分析`,您可根据具体使用场景选择其一。 -- `在线分析`表示配置代码库链接后,TCA客户端拉取代码后进行分析;`客户端分析`在配置本地待扫描代码路径后,无需代码拉取直接分析本地代码。 -- `在线分析`与`客户端分析`具体详情及配置参考[TCA客户端配置详情](../guide/客户端/客户端配置详情.md) - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../guide/代码检查/分析结果查看.md) 等。 - -![分支概览](../../images/start_scan_04.png) diff --git a/web/packages/tca-document/en/quickStarted/tools.md b/web/packages/tca-document/en/quickStarted/tools.md deleted file mode 100644 index a4c47ba0f..000000000 --- a/web/packages/tca-document/en/quickStarted/tools.md +++ /dev/null @@ -1,47 +0,0 @@ -# 工具列表 - -目前 TCA 支持以下工具: - -| 官方工具 | 第三方工具 | -| :--------: | :-------: | -|[0daychecker](https://github.com/Tencent/CodeAnalysis/tree/main/tools/codedog_0Day_checker)| androidlint | -|clangwarning| checkstyle | -|codecount| clang | -|customfilescan| cobra | -|customscan| cpd | -|fbrjs| cppcheck | -|javawarning| cpplint | -|regexfilescan| dart_code_metrics | -|regexscan| dartanalyzer | -|[tca_ql_php_beta](https://github.com/Tencent/CodeAnalysis/tree/main/tools/Hades_Beta)| detekt | -|unusedresource| eslint | -|[collie](https://github.com/Tencent/CodeAnalysis/tree/main/tools/collie/)| eslint_typescript | -|[compass](https://github.com/Tencent/CodeAnalysis/tree/main/tools/compass)| eslint_vue | -|| findbugs | -|| flake8 | -|| [flawfinder](https://github.com/TCATools/flawfinder) | -|| flow | -|| golangcilint | -|| gometalinter | -|| htmlcs | -|| infer_cpp | -|| infer_java | -|| infer_objectivec | -|| [ktlint](https://github.com/TCATools/custom-ktlint) | -|| [kunlun-M](https://github.com/TCATools/common-kunlun.git) | -|| lizard | -|| luacheck | -|| [phpcs](https://github.com/TCATools/custom-phpcs) | -|| pmd | -|| pylint | -|| [rips](https://github.com/TCATools/rips-scanner) | -|| scalastyle | -|| [semgrep](https://github.com/TCATools/custom-semgrep) | -|| [shellcheck](https://github.com/TCATools/shellcheck) | -|| [spotbugs](https://github.com/TCATools/spotbugs) | -|| stylecop | -|| stylelint | -|| swiftlint | -|| [sonarqube](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq.py) | -|| [sonarqube_java](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq_java.py) | -|| [sonarqube_cs](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq_cs.py) | diff --git "a/web/packages/tca-document/images/API\347\232\204\344\270\252\344\272\272\344\273\244\347\211\214.png" "b/web/packages/tca-document/images/API\347\232\204\344\270\252\344\272\272\344\273\244\347\211\214.png" deleted file mode 100644 index 27ce1635c..000000000 Binary files "a/web/packages/tca-document/images/API\347\232\204\344\270\252\344\272\272\344\273\244\347\211\214.png" and /dev/null differ diff --git a/web/packages/tca-document/images/AddRule.png b/web/packages/tca-document/images/AddRule.png deleted file mode 100644 index a8d26ca31..000000000 Binary files a/web/packages/tca-document/images/AddRule.png and /dev/null differ diff --git a/web/packages/tca-document/images/AddRule2.png b/web/packages/tca-document/images/AddRule2.png deleted file mode 100644 index facf51a29..000000000 Binary files a/web/packages/tca-document/images/AddRule2.png and /dev/null differ diff --git a/web/packages/tca-document/images/AddRule3.png b/web/packages/tca-document/images/AddRule3.png deleted file mode 100644 index 6b3e9dd2d..000000000 Binary files a/web/packages/tca-document/images/AddRule3.png and /dev/null differ diff --git a/web/packages/tca-document/images/Fork.png b/web/packages/tca-document/images/Fork.png deleted file mode 100644 index 99895e1b4..000000000 Binary files a/web/packages/tca-document/images/Fork.png and /dev/null differ diff --git a/web/packages/tca-document/images/NewPullRequest.png b/web/packages/tca-document/images/NewPullRequest.png deleted file mode 100644 index ad6b12ebb..000000000 Binary files a/web/packages/tca-document/images/NewPullRequest.png and /dev/null differ diff --git a/web/packages/tca-document/images/PR.png b/web/packages/tca-document/images/PR.png deleted file mode 100644 index 5321bc135..000000000 Binary files a/web/packages/tca-document/images/PR.png and /dev/null differ diff --git a/web/packages/tca-document/images/Welcome.png b/web/packages/tca-document/images/Welcome.png deleted file mode 100644 index 0184d09b4..000000000 Binary files a/web/packages/tca-document/images/Welcome.png and /dev/null differ diff --git a/web/packages/tca-document/images/clientConfigIni.png b/web/packages/tca-document/images/clientConfigIni.png deleted file mode 100644 index 89e05b26a..000000000 Binary files a/web/packages/tca-document/images/clientConfigIni.png and /dev/null differ diff --git a/web/packages/tca-document/images/codelint_01.png b/web/packages/tca-document/images/codelint_01.png deleted file mode 100644 index ce5098c2c..000000000 Binary files a/web/packages/tca-document/images/codelint_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/codelint_02.png b/web/packages/tca-document/images/codelint_02.png deleted file mode 100644 index 406a93799..000000000 Binary files a/web/packages/tca-document/images/codelint_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/codelint_03.png b/web/packages/tca-document/images/codelint_03.png deleted file mode 100644 index d013b2511..000000000 Binary files a/web/packages/tca-document/images/codelint_03.png and /dev/null differ diff --git a/web/packages/tca-document/images/creataAnalysePlan.png b/web/packages/tca-document/images/creataAnalysePlan.png deleted file mode 100644 index 82cdbeeb9..000000000 Binary files a/web/packages/tca-document/images/creataAnalysePlan.png and /dev/null differ diff --git a/web/packages/tca-document/images/createProject.png b/web/packages/tca-document/images/createProject.png deleted file mode 100644 index d0400a326..000000000 Binary files a/web/packages/tca-document/images/createProject.png and /dev/null differ diff --git a/web/packages/tca-document/images/createTeam.png b/web/packages/tca-document/images/createTeam.png deleted file mode 100644 index 5056418b7..000000000 Binary files a/web/packages/tca-document/images/createTeam.png and /dev/null differ diff --git a/web/packages/tca-document/images/create_repo.png b/web/packages/tca-document/images/create_repo.png deleted file mode 100644 index 2dab3e3cf..000000000 Binary files a/web/packages/tca-document/images/create_repo.png and /dev/null differ diff --git a/web/packages/tca-document/images/create_team.png b/web/packages/tca-document/images/create_team.png deleted file mode 100644 index 05fca9102..000000000 Binary files a/web/packages/tca-document/images/create_team.png and /dev/null differ diff --git a/web/packages/tca-document/images/create_team_group.png b/web/packages/tca-document/images/create_team_group.png deleted file mode 100644 index c0d53a0a9..000000000 Binary files a/web/packages/tca-document/images/create_team_group.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_01.png b/web/packages/tca-document/images/customtool_01.png deleted file mode 100644 index 80d9364f2..000000000 Binary files a/web/packages/tca-document/images/customtool_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_02.png b/web/packages/tca-document/images/customtool_02.png deleted file mode 100644 index 6e5d788ac..000000000 Binary files a/web/packages/tca-document/images/customtool_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_03.png b/web/packages/tca-document/images/customtool_03.png deleted file mode 100644 index eca12883a..000000000 Binary files a/web/packages/tca-document/images/customtool_03.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_04.png b/web/packages/tca-document/images/customtool_04.png deleted file mode 100644 index 47f34630e..000000000 Binary files a/web/packages/tca-document/images/customtool_04.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_05.png b/web/packages/tca-document/images/customtool_05.png deleted file mode 100644 index 25bd2c203..000000000 Binary files a/web/packages/tca-document/images/customtool_05.png and /dev/null differ diff --git a/web/packages/tca-document/images/customtool_06.png b/web/packages/tca-document/images/customtool_06.png deleted file mode 100644 index af530ad1b..000000000 Binary files a/web/packages/tca-document/images/customtool_06.png and /dev/null differ diff --git a/web/packages/tca-document/images/fork1.png b/web/packages/tca-document/images/fork1.png deleted file mode 100644 index f93cdcbe5..000000000 Binary files a/web/packages/tca-document/images/fork1.png and /dev/null differ diff --git a/web/packages/tca-document/images/homepage.png b/web/packages/tca-document/images/homepage.png deleted file mode 100644 index b964a420f..000000000 Binary files a/web/packages/tca-document/images/homepage.png and /dev/null differ diff --git a/web/packages/tca-document/images/logo.png b/web/packages/tca-document/images/logo.png deleted file mode 100644 index aab4be80c..000000000 Binary files a/web/packages/tca-document/images/logo.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_job_01.png b/web/packages/tca-document/images/manage_job_01.png deleted file mode 100644 index 973333db7..000000000 Binary files a/web/packages/tca-document/images/manage_job_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_node_01.png b/web/packages/tca-document/images/manage_node_01.png deleted file mode 100644 index 5012308be..000000000 Binary files a/web/packages/tca-document/images/manage_node_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_node_02.png b/web/packages/tca-document/images/manage_node_02.png deleted file mode 100644 index 217aa7d0c..000000000 Binary files a/web/packages/tca-document/images/manage_node_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_node_03.png b/web/packages/tca-document/images/manage_node_03.png deleted file mode 100644 index 1b6067e8d..000000000 Binary files a/web/packages/tca-document/images/manage_node_03.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_node_04.png b/web/packages/tca-document/images/manage_node_04.png deleted file mode 100644 index d6d2c3a6d..000000000 Binary files a/web/packages/tca-document/images/manage_node_04.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_oauth_01.png b/web/packages/tca-document/images/manage_oauth_01.png deleted file mode 100644 index cbc3b1e7b..000000000 Binary files a/web/packages/tca-document/images/manage_oauth_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_oauth_02.png b/web/packages/tca-document/images/manage_oauth_02.png deleted file mode 100644 index 0092c52a1..000000000 Binary files a/web/packages/tca-document/images/manage_oauth_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_org_01.png b/web/packages/tca-document/images/manage_org_01.png deleted file mode 100644 index 37e62f2a0..000000000 Binary files a/web/packages/tca-document/images/manage_org_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_org_02.png b/web/packages/tca-document/images/manage_org_02.png deleted file mode 100644 index 52161dea1..000000000 Binary files a/web/packages/tca-document/images/manage_org_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_team_01.png b/web/packages/tca-document/images/manage_team_01.png deleted file mode 100644 index ff5908bbb..000000000 Binary files a/web/packages/tca-document/images/manage_team_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_tool_01.png b/web/packages/tca-document/images/manage_tool_01.png deleted file mode 100644 index 2cf005f66..000000000 Binary files a/web/packages/tca-document/images/manage_tool_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_user_01.png b/web/packages/tca-document/images/manage_user_01.png deleted file mode 100644 index 8596ee282..000000000 Binary files a/web/packages/tca-document/images/manage_user_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/manage_user_02.png b/web/packages/tca-document/images/manage_user_02.png deleted file mode 100644 index 9a955cc49..000000000 Binary files a/web/packages/tca-document/images/manage_user_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/node_mange.png b/web/packages/tca-document/images/node_mange.png deleted file mode 100644 index f9fcd4760..000000000 Binary files a/web/packages/tca-document/images/node_mange.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_node_manager_1.png b/web/packages/tca-document/images/org_node_manager_1.png deleted file mode 100644 index 375447db2..000000000 Binary files a/web/packages/tca-document/images/org_node_manager_1.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_node_manager_2.png b/web/packages/tca-document/images/org_node_manager_2.png deleted file mode 100644 index db937ee4e..000000000 Binary files a/web/packages/tca-document/images/org_node_manager_2.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_node_process.png b/web/packages/tca-document/images/org_node_process.png deleted file mode 100644 index 758092622..000000000 Binary files a/web/packages/tca-document/images/org_node_process.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_tag_manager.png b/web/packages/tca-document/images/org_tag_manager.png deleted file mode 100644 index f3cfdaa27..000000000 Binary files a/web/packages/tca-document/images/org_tag_manager.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_tag_node.png b/web/packages/tca-document/images/org_tag_node.png deleted file mode 100644 index 890af1469..000000000 Binary files a/web/packages/tca-document/images/org_tag_node.png and /dev/null differ diff --git a/web/packages/tca-document/images/org_tag_scheme.png b/web/packages/tca-document/images/org_tag_scheme.png deleted file mode 100644 index b8c352587..000000000 Binary files a/web/packages/tca-document/images/org_tag_scheme.png and /dev/null differ diff --git a/web/packages/tca-document/images/orgsid.png b/web/packages/tca-document/images/orgsid.png deleted file mode 100644 index 7b53c6d69..000000000 Binary files a/web/packages/tca-document/images/orgsid.png and /dev/null differ diff --git a/web/packages/tca-document/images/personalToken.png b/web/packages/tca-document/images/personalToken.png deleted file mode 100644 index 78e5cdba9..000000000 Binary files a/web/packages/tca-document/images/personalToken.png and /dev/null differ diff --git a/web/packages/tca-document/images/planPage.png b/web/packages/tca-document/images/planPage.png deleted file mode 100644 index eb90909fb..000000000 Binary files a/web/packages/tca-document/images/planPage.png and /dev/null differ diff --git a/web/packages/tca-document/images/registerCodeRepo.png b/web/packages/tca-document/images/registerCodeRepo.png deleted file mode 100644 index 647cdb287..000000000 Binary files a/web/packages/tca-document/images/registerCodeRepo.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_codelint_01.png b/web/packages/tca-document/images/scheme_codelint_01.png deleted file mode 100644 index d2809c35f..000000000 Binary files a/web/packages/tca-document/images/scheme_codelint_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_codelint_02.png b/web/packages/tca-document/images/scheme_codelint_02.png deleted file mode 100644 index 1bd1763f7..000000000 Binary files a/web/packages/tca-document/images/scheme_codelint_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_codelint_03.png b/web/packages/tca-document/images/scheme_codelint_03.png deleted file mode 100644 index fe470afc2..000000000 Binary files a/web/packages/tca-document/images/scheme_codelint_03.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_codelint_04.png b/web/packages/tca-document/images/scheme_codelint_04.png deleted file mode 100644 index 7b83f587e..000000000 Binary files a/web/packages/tca-document/images/scheme_codelint_04.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_template_01.png b/web/packages/tca-document/images/scheme_template_01.png deleted file mode 100644 index cd002101c..000000000 Binary files a/web/packages/tca-document/images/scheme_template_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/scheme_template_02.png b/web/packages/tca-document/images/scheme_template_02.png deleted file mode 100644 index 05e9854ee..000000000 Binary files a/web/packages/tca-document/images/scheme_template_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_01.png b/web/packages/tca-document/images/start_scan_01.png deleted file mode 100644 index f72d232bd..000000000 Binary files a/web/packages/tca-document/images/start_scan_01.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_02.png b/web/packages/tca-document/images/start_scan_02.png deleted file mode 100644 index 0b02dc7d0..000000000 Binary files a/web/packages/tca-document/images/start_scan_02.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_03.png b/web/packages/tca-document/images/start_scan_03.png deleted file mode 100644 index df2611126..000000000 Binary files a/web/packages/tca-document/images/start_scan_03.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_04.png b/web/packages/tca-document/images/start_scan_04.png deleted file mode 100644 index f84b627dd..000000000 Binary files a/web/packages/tca-document/images/start_scan_04.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_05.png b/web/packages/tca-document/images/start_scan_05.png deleted file mode 100644 index 881e3fe9c..000000000 Binary files a/web/packages/tca-document/images/start_scan_05.png and /dev/null differ diff --git a/web/packages/tca-document/images/start_scan_06.png b/web/packages/tca-document/images/start_scan_06.png deleted file mode 100644 index eb9bfc436..000000000 Binary files a/web/packages/tca-document/images/start_scan_06.png and /dev/null differ diff --git a/web/packages/tca-document/images/team.png b/web/packages/tca-document/images/team.png deleted file mode 100644 index e9a8400bd..000000000 Binary files a/web/packages/tca-document/images/team.png and /dev/null differ diff --git a/web/packages/tca-document/images/team_member.png b/web/packages/tca-document/images/team_member.png deleted file mode 100644 index 6a6babb95..000000000 Binary files a/web/packages/tca-document/images/team_member.png and /dev/null differ diff --git a/web/packages/tca-document/package.json b/web/packages/tca-document/package.json deleted file mode 100644 index 624cf0989..000000000 --- a/web/packages/tca-document/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "tca-document", - "version": "1.0.0", - "description": "tca document", - "keywords": [ - "tca", - "document" - ], - "license": "MIT", - "scripts": { - "dev": "vuepress dev", - "build:comment": "echo '构建帮助文档,默认base前缀为document,可根据部署需要进行相应调整'", - "build": "BASE=document vuepress build -d ./dist" - }, - "devDependencies": { - "@vuepress/plugin-search": "^2.0.0-beta.43", - "vuepress": "^2.0.0-beta.42" - } -} \ No newline at end of file diff --git a/web/packages/tca-document/zh/README.md b/web/packages/tca-document/zh/README.md deleted file mode 100644 index 794436693..000000000 --- a/web/packages/tca-document/zh/README.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git "a/web/packages/tca-document/zh/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" "b/web/packages/tca-document/zh/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" deleted file mode 100644 index 5af9d5ac8..000000000 --- "a/web/packages/tca-document/zh/advanced/\344\273\273\345\212\241\345\210\206\345\270\203\345\274\217\346\211\247\350\241\214.md" +++ /dev/null @@ -1,71 +0,0 @@ -# 任务分布式执行 - -## 适用场景 - -- 以往的单机器单进程,性能比较低,工具排队等待时间过长。希望通过并行执行分析来提高分析效率。 - -- 希望尽量使用公共资源或使用专机资源。 - -**为了满足以上需求,TCA已经进行如下支持:** - -- 支持工具在多台机器上并行执行。 - -- 支持指定工具在指定的机器上运行。 - -- 支持与本地启动的任务衔接,加速本地任务扫描。 - -- 配套任务状态监控能力,及时重置初始化超时或机器掉线的任务。 - -:::tip -TCA客户端除了通过localscan命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。和本地分析一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -## 常驻节点配置 - -**前置步骤**:公共/专有机器上已具备客户端。 - -开源版客户端,需要配置相关环境和依赖,可查阅帮助文档中的开源版客户端使用说明(如下图) - - ![helpopensource](https://tencent.github.io/CodeAnalysis/media/helpopensource.png) - (界面右上角图标点击-帮助文档-Client 客户端) - -**1.配置 config.ini 文件** - -将``替换成实际的serve ip(可包含端口号)。 - -**2.启动代码分析常驻节点** - -1. 从TCA前端页面中获取 `token`,前往 个人中心-个人令牌-复制`Token` 。 - - **作为公共节点**:`token`需要具有超级管理员权限(界面右上角图标点-管理入口-用户管理),如使用CodeDog账户的`token`。 - - - **作为专机节点**:该节点仅能分析该token具有权限的项目。 - -2. 进入到client目录下,执行命令: - `python3 codepuppy.py -l codepuppy.log start -t ` - - ![order](https://tencent.github.io/CodeAnalysis/media/order.png) - -3. 启动后,可以在命令行输出或codepuppy.log中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -**3.配置节点** - -:::tip -常驻节点首次启动后,需要到节点管理页面设置节点状态(默认为不可用),将其设置为活跃,用于接收和执行任务。 -::: - -1. 进入TCA节点管理页面。可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 - - ![NodeManagement](https://tencent.github.io/CodeAnalysis/media/Nodemanagement.png) - (界面右上角图标点击-管理入口-节点管理) - -- 常驻节点首次启动后,需将节点状态从不可用(失效)状态切换到活跃(在线)状态。 - - ![StateSwitch](https://tencent.github.io/CodeAnalysis/media/StateSwitch.png) - -- 可以进入工具进程配置页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 - - ![ProcessConfiguration](https://tencent.github.io/CodeAnalysis/media/ProcessConfiguration.png) - -- 节点所属标签会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 - -本功能代码已提交开源版,欢迎使用! :+1: diff --git "a/web/packages/tca-document/zh/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" "b/web/packages/tca-document/zh/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" deleted file mode 100644 index ca4463fe8..000000000 --- "a/web/packages/tca-document/zh/advanced/\351\233\206\346\210\220\344\273\243\347\240\201\345\210\206\346\236\220\345\267\245\345\205\267.md" +++ /dev/null @@ -1,215 +0,0 @@ -# 集成代码分析工具 - -## 初识TCA任务执行机制 - -1. TCA server在接收到开启分析的请求后根据所选规则生成对应的task_request,每个task_request对应一个工具的任务 -2. TCA server将`task_request`分发到能够执行该工具的机器 -3. TCA client在收到task_request后提取出本次任务的工具名也就是其中的`task_name`字段,字段对应于工具的`name`字段 -4. TCA client按照`task_name`在client中的tool目录查找对应python启动脚本 -5. 执行python启动脚本中的内容 - -## 添加分析工具(以tca_ql_php_beta为例) - -根据上述的任务机制添加工具需要做到以下几点 - -1. 让server知道存在`tca_ql_php_beta`工具及其所含的规则 -2. 让server知道哪些客户端可以执行`tca_ql_php_beta`工具 -3. client下载/找到工具所在目录及需要的环境 -4. 让client知道`tca_ql_php_beta`对应的启动脚本是什么 - -### 如何让Server知道存在相应工具 - -1. 找到`server/projects/main/apps/scan_conf/management/commands/open_source`目录 - -2. 创建工具json文件,json文件名尽量对应工具名称方便查看 - -3. json文件内容为(以tca_ql_php_beta为例) - - ```python - [ - { - "name": "tca_ql_php_beta", - "display_name": "Hades_Beta_PHP(展示名称用于前端展示使用)", - "description": "工具描述", - "license": "工具license", - "libscheme_set": [], # 暂时不需要 - "task_processes": [ - "analyze", - "datahandle", - "compile" - ], # 工具进程,包含compile编译, analyze分析, datahandle数据处理 - "scan_app": "codelint", # 代码分析统一为codelint - "scm_url": "", # 暂时为空 - "run_cmd": "", - "envs": null, # 是否需要特殊环境,这里无需填写 - "build_flag": false, # 是否需要编译命令才能运行 - "checkrule_set": [ # 工具包含的规则 - { - "real_name": "deser", # 规则名 - "display_name": "反序列化漏洞", # 规则前端展示,考虑各工具规则名可能晦涩难懂,设置展示名称方便查找 - "severity": "error", # 规则等级 从上到下分为 fatal, error, warning, info 四个等级 - "category": "security", # 规则类别。correctness 功能 security安全 performance性能 usability可用性 accessibility无障碍化 i18n国际化 convention代码风格 other其他 - "rule_title": "反序列化漏洞", # 一句话概括规则简介 - "rule_params": null, # 规则参数 - "languages": [ # 支持语言 - "php" - ], - "solution": "", # 建议的解决方法 - "owner": "", - "labels": [], - "description": "", # 规则详细介绍 - } - ] - } - ] - ``` - -4. 在`server/projects/main/`目录执行`python manage.py loadcheckers --dir open_source tca_ql_php_beta` 加载工具进入数据库 - -## 让server知道哪些客户端可以执行`tca_ql_php_beta`工具 - -1. 进入节点管理页面 - -![节点管理](https://tencent.github.io/CodeAnalysis/media/node_mange.png) - -2. 选择其中一台机器 工具进程配置,勾选其工具进程 - -![工具进程](https://tencent.github.io/CodeAnalysis/media/tool.png) - -## client下载/找到工具所在目录及需要的环境 - -1. 找到puppy-tool-config若没有额外配置则为默认代码库 -2. 修改其中的 ini 配置文件,每个操作系统对应一个ini -3. 以tca_ql_php_beta为例需要做以下修改 - -``` -; env_path 主要填写存放工具文件所在的相对目录,一般都存放/拉取在tools下,会在工具执行前加载到环境变量中提供使用 -[env_path] -ZEUS_BETA_HOME : Zeus_Beta -HADES_BETA_HOME : Hades_Beta - -; toolz_url -[tool_url] 主要填写工具的git仓库,这里因为tca_ql_php_beta直接使用tools下的目录所以不用再进行额外拉取也无需再写 -CPPCHECK : ${base_value:git_url}/linux-cppcheck-1.78 - -; 各工具配置 以tca_ql_php_beta为例 -; env_path 填写上面需要加载的环境变量 -; env_value 通用环境变量,一般无需填写如果有需求需要现在 [env_value] 中定义好再填写 -; path 工具所在目录填写上面的定义 -; tool_url 工具git仓库,使用本地相对目录故为空 -[tca_ql_php_beta] -env_path : ZEUS_BETA_HOME;HADES_BETA_HOME -env_value : -path : ${env_path:ZEUS_BETA_HOME};${env_path:HADES_BETA_HOME} -tool_url : - -``` - -## 让client知道`tca_ql_php_beta`对应的启动脚本是什么 - -1. 以上述步骤在`client/tool`目录添加脚本`tca_ql_php_beta.py`作为启动脚本 注:启动脚本必须与工具名称相同 - -2. 编写脚本 - -### 脚本编写规范 - -以`tca_ql_php_beta`为例 - -``` - -from task.codelintmodel import CodeLintModel -from util.logutil import LogPrinter -from util.subprocc import SubProcController - -logger = LogPrinter() - - -class TcaQlPHPBeta(CodeLintModel): - # 代码分析工具集成基类CodeLintModel - def __init__(self, params): - logger.info("找到工具了Q_Q") - super().__init__(params) - - def compile(self, params): - logger.info("开始编译了Q_Q") - build_cmd = params.get('build_cmd', None) # 从params中获取编译命令, params内容可以在最后附录查看 - lang = "php" - do_some_things() - - def analyze(self, params): - logger.info("开始分析了Q_Q") - lang = "php" - HADES_HOME = envs.get("HADES_BETA_HOME", None) - output_json = "result.json" - sp = SubProcController( - command=["Hades", "analyze", "test.php", "-o", output_json], - cwd=HADES_HOME, - stdout_line_callback=subprocc_log, - stderr_line_callback=subprocc_log, - ) - sp.wait() # 执行工具分析命令 - issues = [] - # 工具结果输出到output_json,具体工具可能有所不同 - if os.path.exists(output_json): - with open(output_json, "r") as result_reader: - result = json.load(result_reader) - issues.extend(result) - return issues - -tool = TcaQlPHPBeta # 必须,必须包含tool变量并且为该工具的类 -``` - -1. 脚本必须包含analyze方法,如果有配置编译进程也需要相应的compile方法来做编译相关工作,datahandle函数不用自定义基类方法已经够用了。方法执行顺序为 compile -> analyze -> datahandle -2. params参数为`task_request`中的`task_params`字段,具体字段将在最后附录进行说明 -3. anlyze方法必须有返回值,返回值为issue列表,issue格式为 - -``` -{ - "path": "文件相对路径", - "line": "行号,int类型", - "column": "列号, int类型,如果工具没有输出列号信息,可以用0代替", - "msg": "提示信息", - "rule": "规则名称,可以根据需要输出不同的规则名", - "refs": [ - { - "line": "回溯行号", - "msg": "提示信息", - "tag": "用一个词简要标记该行信息,比如uninit_member,member_decl等,如果没有也可以都写成一样的", - "path": "回溯行所在文件绝对路径" - }, - ... - ] -} -说明: - refs:可选,记录问题回溯路径信息。比如当前文件的回溯路径其他的3行代码,可以将这三行的路径及提示信息,按顺序添加到refs数组中。 -``` - -# PR - -如果有意公开您添加的工具欢迎发起PR - -注:别忘了puppy-tool-config 也需要PR - -# 附录 - -## params 表格 - -| 字段 | 说明 | 类型 | -| --- | --- | --- | -| scan_languages | 语言 | 字符串列表如 ["python", "php"] | -| pre_cmd | 编译前置命令 | 字符串 | -| build_cmd | 编译命令 | 字符串 | -| envs | 额外环境变量 | 字符串 | -| scm_last_revision | 上次成功分析的代码版本,增量使用 | 字符串 | -| incr_scan | 是否为增量分析 | bool | -| rules | 规则名称列表,只有规则名 | 字符串列表 | -| rule_list | 详细的规则列表包含规则名和规则参数等 | 字典列表 | -| checktool | 工具详细信息,执行一般用不到 | 字典 | -| path_filters | 过滤路径 | 字典 | -| scm_url | 代码库url | 字符串 | -| source_dir | 代码库本地目录 | 字符串 | -| work_dir | 本次任务的work_dir目录 | 字符串 | -| project_id | 分析项目id | int | -| repo_id | 仓库id | int | -| task_id | 任务id | int | -| job_id | 本次分析的id | int | diff --git a/web/packages/tca-document/zh/api/README.md b/web/packages/tca-document/zh/api/README.md deleted file mode 100644 index 701f35131..000000000 --- a/web/packages/tca-document/zh/api/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# 接口调用说明 - -## 接口地址 - -`http://{host}/server/` - -注:host 指当前浏览器访问该文档的 URL 域名部分。 - -## 接口鉴权方式 - -发起请求时,需要在头部中添加以下格式形式,对应的 value 请看下面获取方式 - -```json -{ - "Authorization": "当前user的token" -} -``` - -获取 token 位置(个人中心-个人令牌): - -![API的个人令牌](../../images/API的个人令牌.png) - -## 获取 org_sid 和 project_team 信息 - -通过平台访问具体代码库扫描情况时,可从 URL 中获取对应 org_sid 和 project_team 字段,查看方式如下例子: - -代码库扫描地址:`http://{host}/t/xxx/p/yyy/code-analysis/repos/1/projects?limit=10&offset=0` - -其中,org_sid 为`xxx`字段,project_team 为 `yyy`字段 - -## Example - -```python -import requests -# 假设: -# 当前域名为http://tca.com/,当前org_sid为helloworld -# 获取helloworld团队下的hellotca项目下登记的代码库 -url="http://tca.com/server/main/api/orgs/helloworld/teams/hellotca/repos/?limit=12&offset=0" -headers = { - "Authorization": token, -} - -response = requests.get(url, headers=headers) -print(response.json()) -# 结果如下: -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 23, - "name": "repo_name", - "scm_url": "http://git.repo.com/group/repo_name", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-05-14 02:34:44.509118+00:00", - "recent_active": { - "id": 27, - "branch_name": "master", - "active_time": "2021-05-14 02:34:44.509118+00:00", - "total_line_num": 1, - "code_line_num": 1 - }, - "created_from": "tca", - "creator": { - "username": "author", - "nickname": "author", - "status": 1, - "avatar": "url", - "org": "org_name" - }, - "symbol": null, - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "test", - "scm_platform": 2, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": "url", - "org": "org_name" - } - }, - "auth_type": "ssh_token", - "created_time": "2021-05-14T10:34:44.552859+08:00", - "modified_time": "2021-05-14T10:34:44.552887+08:00" - }, - "project_team": { - "name": "test", - "display_name": "测试", - "status": 1, - "org_sid": "test" - } - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 分页方式 - -平台返回的数据分页格式是使用`limit`和`offset`参数进行分页处理 - -比如:`server/main/api/orgs//teams/?limit=12&offset=12`获取得到的数据是从第 13 条开始获取 diff --git "a/web/packages/tca-document/zh/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/zh/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 5a8befdb9..000000000 --- "a/web/packages/tca-document/zh/api/\344\273\243\347\240\201\345\272\246\351\207\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,708 +0,0 @@ -# 代码度量数据管理 - -## 查看指定项目的圈复杂度文件列表 - -```bash -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| scan_open | int | 发现问题的扫描编号 | -| scan_close | int | 修复问题的扫描编号 | -| worse | boolean | 圈复杂度是否恶化 | -| over_cc_sum_gte | int | 圈复杂度总和最小值 | -| over_cc_sum_lte | int | 圈复杂度总和最大值 | -| over_cc_avg_gte | int | 平均圈复杂度最小值 | -| over_cc_avg_lte | int | 平均圈复杂度总和最大值 | -| over_cc_func_count_gte | int | 超标圈复杂度函数个数最小值 | -| over_cc_func_count_lte | int | 超标圈复杂度函数个数最大值 | - -#### 返回参数 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的圈复杂度文件问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccfiles//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的圈复杂度问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度文件列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_close_id | int | 修复问题的扫描编号 | -| worse | boolean | 圈复杂度是否恶化 | -| over_cc_sum_gte | int | 圈复杂度总和最小值 | -| over_cc_sum_lte | int | 圈复杂度总和最大值 | -| over_cc_avg_gte | int | 平均圈复杂度最小值 | -| over_cc_avg_lte | int | 平均圈复杂度总和最大值 | -| over_cc_func_count_gte | int | 超标圈复杂度函数个数最小值 | -| over_cc_func_count_lte | int | 超标圈复杂度函数个数最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 32, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "tapd_url": null, - "created_time": "2020-06-02T10:59:09.418250+08:00", - "creator": null, - "modified_time": "2020-06-03T16:17:40.892224+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "over_func_cc": 0, - "over_cc_sum": 0, - "over_cc_avg": 0, - "over_cc_func_count": 0, - "diff_over_func_cc": 0, - "diff_over_cc_sum": 0, - "diff_over_cc_avg": 0, - "diff_over_cc_func_count": 0, - "worse": false, - "file_path": "test/demo.py", - "state": 3, - "change_type": 0, - "last_modifier": "author1", - "author": null, - "related_modifiers": "author1;author2", - "file_owners": null, - "language": "python", - "tapd_ws_id": null, - "tapd_bug_id": null, - "revision": null, - "ci_time": null, - "project": 1, - "scan_open": 1, - "scan_close": 2 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度文件问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccfiles//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目指定扫描的圈复杂度问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/scans//ccissues/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| status | str | 问题状态,1为需要关注,2为无需关注,可多选,格式为1,2,3 | -| change_type | str | 圈复杂度变化情况,0为无,1为新增,2为删除,3为无变化,可多选,格式为1,2,3 | -| author | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| ccn_gte | str | 圈复杂度最小值 | -| ccn_lte | str | 圈复杂度最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "created_time": "2021-02-19T15:30:20.968525+08:00", - "creator": null, - "modified_time": "2021-02-19T15:30:20.968532+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "ccn": 22, - "g_cc_hash": null, - "cc_hash": null, - "file_path": "test/demo.py", - "func_name": "test_func", - "func_param_num": 4, - "long_name": "test_func( project , result_data , scan , task_params )", - "change_type": 0, - "status": 1, - "last_modifier": "author", - "author": null, - "related_modifiers": "author,author2", - "is_tapdbug": false, - "ignore_time": null, - "is_latest": true, - "language": "python", - "revision": "revision", - "ci_time": "2020-03-18T19:46:48+08:00", - "diff_ccn": null, - "project": 1, - "scan_open": 1, - "scan_close": null - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的重复文件列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| issue__state | str | 问题状态, 1为未处理,2为可忽略,3为关闭,可多选,格式为1,2,3 | -| change_type | str | 重复文件更改类型,add为新增,del为删除,mod为删除,可多选,格式为add,del,mod | -| issue__owner | str | 问题责任人 | -| last_modifier | str | 最近修改人 | -| file_path | str | 文件路径 | -| duplicate_rate_gte | int | 重复率最小值 | -| duplicate_rate_lte | int | 重复率最大值 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo": 1, - "issue": { - "id": 1, - "state": 1, - "owner": "author" - }, - "project_id": 1, - "scan_id": 1, - "issue_id": 1, - "issue_state": 1, - "issue_owner": "author", - "dir_path": "test", - "file_name": "demo.py", - "file_path": "test/demo.py", - "duplicate_rate": 4.63, - "total_line_count": 259, - "total_duplicate_line_count": 12, - "distinct_hash_num": 1, - "block_num": 1, - "last_modifier": "author", - "change_type": null, - "scm_revision": "12345678abc", - "is_latest": true - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定重复文件 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles// -``` - -#### 返回结果 - -```JSON -{ - "data": { - "id": 1, - "repo": 1, - "issue": { - "id": 1, - "state": 1, - "owner": "author" - }, - "blocks": [ - { - "id": 1, - "duplicate_file": 1, - "project_id": 1, - "scan_id": 1, - "duplicate_file_id": 1, - "token_num": 120, - "duplicate_times": 2, - "duplicate_rate": 4.63, - "start_line_num": 216, - "end_line_num": 227, - "duplicate_line_count": 12, - "last_modifier": "author", - "change_type": null, - "related_modifiers": "author" - } - ], - "duplicate_rate_trend": 0.0, - "project_id": 1815, - "scan_id": 488, - "issue_id": 3, - "issue_state": 1, - "issue_owner": "author", - "dir_path": "test", - "file_name": "demo.py", - "file_path": "test/demo.py", - "duplicate_rate": 4.63, - "total_line_count": 259, - "total_duplicate_line_count": 12, - "distinct_hash_num": 1, - "block_num": 1, - "last_modifier": "author", - "change_type": null, - "scm_revision": "xxx", - "is_latest": true - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定文件的重复块列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/dupfiles//blocks/ -``` - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "duplicate_file": 1, - "project_id": 1, - "scan_id": 1, - "duplicate_file_id": 1, - "token_num": 120, - "duplicate_times": 2, - "duplicate_rate": 4.63, - "start_line_num": 216, - "end_line_num": 227, - "duplicate_line_count": 12, - "last_modifier": "author", - "change_type": null, - "related_modifiers": "author" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的文件行数列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codemetric/clocfiles/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| change_type | str | 改变类型(add、mod、del),支持多值,使用英文逗号','分隔 | -| file_path | str | 文件路径 | - -#### 返回结果 - -```JSON -{ - "data": { - "count": 1, - "next": "", - "previous": null, - "results": [ - { - "id": 1, - "code_line_num": 108587, - "comment_line_num": 0, - "blank_line_num": 0, - "total_line_num": 108587, - "add_code_line_num": 108587, - "add_comment_line_num": 0, - "add_blank_line_num": 0, - "add_total_line_num": 108587, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1, - "scan_id": 1, - "is_latest": true, - "dir_path": "test", - "file_name": "test.json", - "language": "JSON", - "change_type": "add" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的语言列表 - -``` -GET server/analysis/api/orgs//teams//repos//projects//codemetric/cloclangs/ -``` - -#### 返回结果 - -```JSON -{ - "data": { - "count": 2, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "code_line_num": 9753, - "comment_line_num": 4220, - "blank_line_num": 2454, - "total_line_num": 16427, - "add_code_line_num": 9753, - "add_comment_line_num": 4220, - "add_blank_line_num": 2454, - "add_total_line_num": 16427, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1815, - "scan_id": 695, - "is_latest": true, - "name": "Python", - "file_num": 165 - }, - { - "id": 2, - "code_line_num": 379, - "comment_line_num": 0, - "blank_line_num": 153, - "total_line_num": 532, - "add_code_line_num": 379, - "add_comment_line_num": 0, - "add_blank_line_num": 153, - "add_total_line_num": 532, - "mod_code_line_num": 0, - "mod_comment_line_num": 0, - "mod_blank_line_num": 0, - "mod_total_line_num": 0, - "del_code_line_num": 0, - "del_comment_line_num": 0, - "del_blank_line_num": 0, - "del_total_line_num": 0, - "project_id": 1815, - "scan_id": 695, - "is_latest": true, - "name": "Markdown", - "file_num": 7 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` diff --git "a/web/packages/tca-document/zh/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/zh/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index fc89e3982..000000000 --- "a/web/packages/tca-document/zh/api/\344\273\243\347\240\201\346\211\253\346\217\217\346\225\260\346\215\256\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,274 +0,0 @@ -# 代码扫描数据管理 - -## 查看扫描问题列表 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/issues/ -``` - -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open | int | 发现问题的扫描编号 | -| scan_fix | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间,格式为"2021-01-01 00:00:00" | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "file_path": "test/demo.py", - "project": 1, - "repo": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checktool_name": "xxx", - "msg": "xxx", - "state": 3, - "resolution": 1, - "author": "author", - "author_email": null, - "severity": 2, - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "file_owners": null, - "is_external": false, - "scm_url": "", - "real_file_path": "", - "scan_open": 1, - "scan_fix": 2, - "fixed_time": "2021-02-19T15:25:15.152350+08:00" - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看问题详情 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/issues// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "issue_details": [ - { - "id": 1, - "issue_refers": [], - "creator": null, - "modifier": null, - "deleted_time": null, - "deleter": null, - "issuedetail_uuid": "0fcc376e-7283-11eb-bd53-5254005e71ca", - "checkrule_real_name": "xxx", - "checktool_name": "xxx", - "author": "author", - "author_email": null, - "line": 1809, - "column": 15, - "scan_revision": "scan_revision", - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "real_revision": "", - "created_time": "2021-02-19T15:21:19.625658+08:00", - "modified_time": "2021-02-19T15:21:19.625662+08:00", - "issue": null, - "project": 1 - } - ], - "is_external": false, - "repo": 1, - "author": "author", - "created_time": "2021-02-19T15:21:19.625685+08:00", - "creator": null, - "modifier": null, - "deleted_time": null, - "deleter": null, - "file_path": "test/demo.py", - "file_hash": "xxx", - "scm_url": "", - "real_file_path": "", - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "state": 3, - "resolution": 1, - "scan_revision": null, - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2021-02-02T13:31:38+08:00", - "file_owners": null, - "fixed_time": "2021-02-19T15:25:15.152350+08:00", - "tapd_ws_id": null, - "tapd_bug_id": null, - "modified_time": "2021-02-19T15:25:17.807478+08:00", - "project": 1, - "scan_open": 1, - "scan_fix": 2 - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` - -## 查看每次扫描的问题列表 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/scans//issues/ -``` -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_fix_id | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间 | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo_id": 1, - "project_id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "file_path": "test/demo.py", - "scm_url": "", - "real_file_path": "", - "line": 21, - "column": 68, - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "msg": "xxx", - "state": 1, - "resolution": null, - "author": "author", - "scan_open_id": 1, - "scan_fix_id": null, - "issuedetail_uuid": "26d7ba88-8268-11eb-a304-5254005e71ca", - "scan_revision": "scan_revision", - "real_revision": "", - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2019-07-01T10:28:19+08:00", - "file_owners": null, - "created_time": "2021-03-11T20:49:00.539537+08:00", - "fixed_time": null - } - ] - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` - - -## 查看指定CR扫描的问题列表 -``` -GET /server/analysis/api/orgs//teams//repos//projects//codelint/crscans//issues/ -``` -#### 参数 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| state | str | 问题状态, 1为未处理,2为已处理,3为关闭,可多选,格式为1,2,3 | -| severity | str | 严重程度, 1为致命,2为错误,3为警告,4为提示,可多选,格式为1,2,3,4 | -| resolution | str | 解决方式, 0为无,1为修复,2为无需修复,3为误报,4为重复单过滤,5为路径过滤,6为规则移除 | -| author | str | 问题责任人 | -| scan_open_id | int | 发现问题的扫描编号 | -| scan_fix_id | int | 修复问题的扫描编号 | -| ci_time_gte | str | 修复问题的起始时间 | -| ci_time_lte | str | 修复问题的结束时间 | -| file_path | str | 文件路径 | -| checkrule_display_name | str | 检查规则名 | -| checkpackage | int | 问题所属的规则包 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "repo_id": 1, - "project_id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "file_path": "test/demo.py", - "scm_url": "", - "real_file_path": "", - "line": 21, - "column": 68, - "checkrule_gid": 1, - "checkrule_real_name": "xxx", - "checkrule_display_name": "xxx", - "checkrule_rule_title": "xxx", - "checktool_name": "xxx", - "category": 7, - "msg": "xxx", - "state": 1, - "resolution": null, - "author": "author", - "scan_open_id": 1, - "scan_fix_id": null, - "issuedetail_uuid": "26d7ba88-8268-11eb-a304-5254005e71ca", - "scan_revision": "scan_revision", - "real_revision": "", - "severity": 2, - "language": "python", - "revision": "revision", - "ci_time": "2019-07-01T10:28:19+08:00", - "file_owners": null, - "created_time": "2021-03-11T20:49:00.539537+08:00", - "fixed_time": null - } - ] - }, - "code": 0, - "msg": "xxx", - "status_code": 200 -} -``` \ No newline at end of file diff --git "a/web/packages/tca-document/zh/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/zh/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 54e3b6a3d..000000000 --- "a/web/packages/tca-document/zh/api/\344\273\273\345\212\241\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,132 +0,0 @@ -# 任务管理模块 - -## 执行指定代码库指定分支项目扫描任务 - -``` -POST /server/main/api/orgs//teams//repos//projects//scans/create/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| incr_scan | bool | 增量扫描标志,true表示增量,false表示全量 | -| async_flag | bool | 异步启动标志,true表示异步,false表示同步,建议选择异步 | -| force_create | bool | 强制启动标志,true表示强制启动,不等待上一个任务结束 | - -#### 返回结果 -```JSON -{ - "job": { - "id": 7974 - }, - "scan": { - "id": 5528 - } -} -``` - -## 查看指定项目的任务列表 -``` -GET /server/main/api/orgs//teams//repos//projects//jobs/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| create_time_gte | datetime | 最小任务启动时间 | -| create_time_lte | datetime | 最大任务启动时间 | -| result_code_gte | int | 最小错误码值 | -| result_code_lte | int | 最大错误码值 | -| result_msg | str | 结果信息 | -| state | int | 任务状态, 0为等待中,1为执行中,2为关闭,3为入库中,可多选,格式为1,2,3 | -| created_from | str | 创建来源 | -| creator | str | 创建用户 | - - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "state": 2, - "result_code": 0, - "result_msg": "success", - "code_line_num": 1000, - "comment_line_num": 5, - "blank_line_num": 305, - "total_line_num": 1400 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定项目的指定任务详情 - -``` -GET /server/main/api/orgs//teams//repos//projects//jobs//detail/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "scan_id": 1, - "create_time": "2021-01-28T10:27:26.442961+08:00", - "waiting_time": "1", - "start_time": "2021-01-28T11:14:56.760427+08:00", - "execute_time": "3", - "project": { - "id": 1, - "branch": "master", - "repo_id": 1, - "scan_scheme": 1, - "repo_scm_url": "http://github.com/xxx/test_demo.git" - }, - "end_time": "2021-01-28T11:14:59.760427+08:00", - "expire_time": "2021-01-28T14:07:52.968932+08:00", - "task_num": 1, - "task_done": 1, - "tasks": [ - { - "id": 1, - "module": "codelint", - "task_name": "pylint", - "progress_rate": 1, - "state": 2, - "result_code": 0, - "result_msg": "success", - "result_path": null - } - ], - "co_jobs": [], - "state": 2, - "result_code": 0, - "result_code_msg": null, - "result_msg": "success", - "result_path": null, - "remarks": null, - "remarked_by": null, - "code_line_num": 1000, - "comment_line_num": 5, - "blank_line_num": 305, - "total_line_num": 1400, - "created_from": "codedog_web", - "creator": "creator" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - diff --git "a/web/packages/tca-document/zh/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" "b/web/packages/tca-document/zh/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" deleted file mode 100644 index 434e73de3..000000000 --- "a/web/packages/tca-document/zh/api/\345\257\271\350\261\241\344\270\273\350\246\201\345\255\227\346\256\265\350\257\264\346\230\216.md" +++ /dev/null @@ -1,59 +0,0 @@ -# 对象主要字段说明 - -注:以下字段用于参考,具体字段格式需要以具体接口返回为准 - -## 团队(org): -``` -org_sid: str,团队编号 -name: str,团队名称 -description: str,团队描述 -certificated: boolean,团队认证标志位 -created_time: datetime,团队创建时间 -updated_time: datetime,团队更新时间 -admins: list,管理员列表 -project_count: int,分析任务数量 -team_count: int,项目组数量 -user_count: int,成员数量 -owner: str,负责人名称 -tel_number: str,负责人电话 -address: str,办公地址 -``` - -## 项目(team): -``` -name: str,项目组名称 -display_name: str,项目组展示名称 -description: str,项目组描述信息 -``` - -## 代码库(repository): -``` -name: str,代码库名称 -scm_url: str,代码库地址 -scm_type: int,代码库类型 -created_from: str,创建来源 -state:str,代码库状态,1表示活跃,2表示失活,3表示暂停使用 -labels:list,标签 -project_team: 项目 -organization: 团队 -``` - -## 扫描方案(scanscheme): -``` -name: str,扫描方案名称 -repo:关联的代码库 -refer_scheme: 参照的扫描方案 -description: str,描述 -tag: 执行标签 -languages: 包含语言 -default_flag: boolean,默认方案标志 -created_from: str,创建来源 -ignore_merged_issue: boolean,过滤其他分支引入的问题,默认False,不过滤 -ignore_branch_issue: str,过滤指定分支引入的问题 -ignore_submodule_clone: boolean,不拉取子模块,默认False -ignore_submodule_issue: boolean,忽略子模块问题,默认False -issue_global_ignore: boolean,开启问题全局忽略,默认False -daily_save: boolean,日常扫描记录保存7天开关,默认False -lfs_flag: boolean,自动拉取lfs文件,默认True -status: int,扫描方案状态,1为活跃,2为废弃 -``` \ No newline at end of file diff --git "a/web/packages/tca-document/zh/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/zh/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index 089b93059..000000000 --- "a/web/packages/tca-document/zh/api/\347\273\223\346\236\234\346\246\202\350\247\210\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,812 +0,0 @@ -# 代码扫描管理 - -## 查看项目扫描最新结果概览 -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/ -``` - -#### 返回结果 -```JSON -{ - "lintscan": { - "issue_open_num": 74, - "issue_fix_num": 439, - "issue_detail_num": 310, - "scan": { - "id": 1, - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "execute_time": "00:02:17.844712" - }, - "current_scan": { - "active_category_detail": { - "convention": 70, - "other": 4 - }, - "active_severity_detail": { - "error": 69, - "warning": 5 - }, - "issue_open_num": 74, - "issue_fix_num": 439 - }, - "total": { - "state_detail": { - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "category_detail": { - "convention": { - "active": 184, - "resolved": 13, - "closed": 21143 - }, - "other": { - "active": 13, - "closed": 154 - }, - "correctness": { - "closed": 1997 - }, - "performance": { - "closed": 3 - } - }, - "severity_detail": { - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - }, - "status": 0, - "text": "成功", - "description": null, - "scan_summary": { - "convention": { - "error": { - "rule_count": 7, - "active": 65 - }, - "warning": { - "rule_count": 2, - "active": 5 - } - }, - "other": { - "error": { - "rule_count": 1, - "active": 4 - } - } - }, - "total_summary": { - "correctness": { - "error": { - "rule_count": 16, - "closed": 1315 - }, - "warning": { - "rule_count": 10, - "closed": 629 - }, - "info": { - "rule_count": 1, - "closed": 53 - } - }, - "performance": { - "warning": { - "rule_count": 1, - "closed": 3 - } - }, - "convention": { - "error": { - "rule_count": 42, - "active": 149, - "resolved": 11, - "closed": 18778 - }, - "warning": { - "rule_count": 17, - "active": 35, - "resolved": 2, - "closed": 2298 - }, - "info": { - "rule_count": 1, - "closed": 67 - } - }, - "other": { - "error": { - "rule_count": 2, - "active": 8, - "closed": 20 - }, - "warning": { - "rule_count": 1, - "active": 5 - }, - "info": { - "rule_count": 3, - "closed": 134 - } - } - } - }, - "cyclomaticcomplexityscan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "min_ccn": 20, - "over_cc_func_count": 6, - "under_cc_func_count": 796, - "diff_over_cc_func_count": 0, - "over_cc_func_average": 22.333333333333332, - "cc_func_average": 2.5099750623441395, - "over_cc_sum": 14, - "cc_average_of_lines": 1.0422094841063054 - }, - "custom_summary": null, - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", - "diff_cc_num": 0, - "cc_open_num": 6, - "cc_average_of_lines": 1.0422094841063054, - "cc_fix_num": 0, - "worse_cc_file_num": 0, - "min_ccn": 20, - "code_line_num": 13433, - "scan": 1 - }, - "duplicatescan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "exhi_risk": { - "range": [ - 0.2, - 1 - ], - "file_count": 1, - "diff": { - "diff_file_count": 0 - } - }, - "high_risk": { - "range": [ - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { - "range": [ - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { - "range": [ - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, - "last_revision": "last_revision", - "duplicate_file_count": 8, - "duplicate_block_count": 55, - "duplicate_line_count": 1177, - "diff_duplicate_block_count": 0, - "diff_duplicate_line_count": 0, - "close_issue_count": 0, - "new_issue_count": 0, - "reopen_issue_count": 5, - "ignored_issue_count": 0, - "duplicate_rate": 4.98, - "unique_duplicate_line_count": 1083, - "total_duplicate_line_count": 1083, - "total_line_count": 21745, - "scan": 1 - }, - "clocscan": { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "last_revision": "last_revision", - "code_line_num": 140490, - "comment_line_num": 5410, - "blank_line_num": 3408, - "total_line_num": 149308, - "add_code_line_num": 6673, - "add_comment_line_num": 2309, - "add_blank_line_num": 1289, - "add_total_line_num": 10271, - "mod_code_line_num": 965, - "mod_comment_line_num": 297, - "mod_blank_line_num": 0, - "mod_total_line_num": 1262, - "del_code_line_num": 35844, - "del_comment_line_num": 2117, - "del_blank_line_num": 1794, - "del_total_line_num": 39755, - "scan": 1 - } -} -``` - -## 查看项目代码最新扫描结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/latestscan/ -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_revision | str | 指定查询的扫描版本号,如不指定则为当前项目最新的一次扫描 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, # 扫描编号 - "repo_id": 1, # 代码库编号 - "project_id": 1, # 项目编号 - "job_gid": 1, # 关联任务编号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "current_revision": "current_revision", # 扫描版本号 - "result_code": 0, # 扫描任务结果码,0表示正常 - "result_code_msg": "成功", - "result_msg": null, - "lintscan": { # 代码扫描结果信息 - "current_scan": { # 本次扫描信息 - "active_severity_detail": { # 不同严重级别的活跃问题数,包含 fatal(1-致命), error(2-错误), warning(3-警告), info(4-提示) - "error": 69, - "warning": 5 - }, - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2 # 本次扫描关闭存量问题数 - }, - "total": { # 当前项目整体信息 - "state_detail": { # 不同处理状态的问题数,包含 active(1-活跃)、resolved(2-已处理)、closed(3-已关闭) - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "severity_detail": { # 不同严重级别下不同处理状态的问题量 - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - } - }, - "duplicatescan": { # 重复代码扫描结果信息 - "id": 1, # 扫描任务编号 - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "default_summary": { # 默认概览 - "exhi_risk": { # 极高风险 - "range": [ # 重复率范围: 0.2-1 - 0.2, - 1 - ], - "file_count": 1, # 文件数量 - "diff": { # 增量数据 - "diff_file_count": 0 # 增量文件数量 - } - }, - "high_risk": { # 高风险 - "range": [ # 重复率范围:0.11-0.2 - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { # 中风险 - "range": [ # 重复率范围:0.05-0.11 - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { # 低风险 - "range": [ # 重复率范围:0-0.05 - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, # 自定义概览数据 - "last_revision": "2010ef28ff3a26424d4e8f32df022f90cd682eda", # 上次扫描版本号 - "duplicate_file_count": 8, # 重复文件数量 - "duplicate_block_count": 55, # 重复代码块数量 - "duplicate_line_count": 1177, # 重复代码行数 - "diff_duplicate_block_count": 0, # 增量重复代码块数量 - "diff_duplicate_line_count": 0, # 增量重复代码行数 - "close_issue_count": 0, # 关闭问题数 - "new_issue_count": 0, # 新增问题数 - "reopen_issue_count": 5, # 重新打开问题数 - "ignored_issue_count": 0, # 忽略问题数 - "duplicate_rate": 4.98, # 重复率 - "unique_duplicate_line_count": 1083, # 去重后的重复代码行数 - "total_duplicate_line_count": 1083, # 项目总的去重后的重复代码行数 - "total_line_count": 21745, # 项目总行书 - "scan": 1 # 关联扫描任务编号 - }, - "cyclomaticcomplexityscan": { # 圈复杂度扫描数据 - "id": 1, # 圈复杂度扫描编号 - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { # 默认概览数据 - "min_ccn": 20, # 最小圈复杂度阈值 - "over_cc_func_count": 6, # 超标函数数量 - "under_cc_func_count": 796, # 未超标函数数量 - "diff_over_cc_func_count": 0, # 增量超标函数数据 - "over_cc_func_average": 22.333333333333332, # 平均超标圈复杂度 - "cc_func_average": 2.5099750623441395, # 平均圈复杂度 - "over_cc_sum": 14, # 文件超标方法圈复杂度超过阈值的差值之和 - "cc_average_of_lines": 1.0422094841063054 # 千行代码平均圈复杂度 - }, - "custom_summary": null, # 自定义概览数据 - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", # 上一次扫描版本号 - "diff_cc_num": 0, # 增量超标函数数量 - "cc_open_num": 6, # 超标函数量 - "cc_average_of_lines": 1.0422094841063054, # 千行代码平均圈复杂度 - "cc_fix_num": 0, # 修复数量 - "worse_cc_file_num": 0, # 圈复杂度恶化的文件数据 - "min_ccn": 20, # 最小圈复杂度阈值 - "code_line_num": 13433, # 代码行数 - "scan": 1 - }, - "clocscan": { - "id": 1, - "scan_revision": "scan_revision", # 扫描版本号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描时间 - "last_revision": "last_revision", # 上一次扫描版本号 - "code_line_num": 140490, # 代码行数 - "comment_line_num": 5410, # 注释行数 - "blank_line_num": 3408, # 空白行数 - "total_line_num": 149308, # 总行数 - "add_code_line_num": 6673, # 增加的代码行数 - "add_comment_line_num": 2309, # 增加的注释行数 - "add_blank_line_num": 1289, # 增加的空白行数 - "add_total_line_num": 10271, # 增加的总行数 - "mod_code_line_num": 965, # 修改的代码行数 - "mod_comment_line_num": 297, # 修改的注释行数 - "mod_blank_line_num": 0, # 修改的空白行数 - "mod_total_line_num": 1262, # 修改的总行数 - "del_code_line_num": 35844, # 删除的代码行数 - "del_comment_line_num": 2117, # 删除的注释行数 - "del_blank_line_num": 1794, # 删除的空白行数 - "del_total_line_num": 39755, # 删除的总行数 - "scan": 1 - } - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 查看项目代码扫描结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/lintscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2, # 本次扫描关闭存量问题数 - "issue_detail_num": 310, # 本次扫描上报原始问题数(问题展示会进行聚合) - "scan": { # 扫描信息 - "id": 1, # 扫描任务编号 - "scan_time": "2021-03-11T20:46:44.171607+08:00", # 扫描开始时间 - "execute_time": "00:02:17.844712" # 扫描执行耗时 - }, - "current_scan": { # 本次扫描信息 - "active_category_detail": { # 活跃问题分类,包含 CORRECTNESS(1-功能)、SECURITY(2-安全)、PERFORMANCE(3-性能)、USABILITY(4-可用性)、ACCESSIBILITY(5-无障碍化)、I18N(6-国际化)、CONVENTION(7-代码风格)、OTHER(8-其他) - "convention": 70, # 代码风格类型问题 - "other": 4 # 其他类型问题 - }, - "active_severity_detail": { # 不同严重级别的活跃问题数,包含 fatal(1-致命), error(2-错误), warning(3-警告), info(4-提示) - "error": 69, - "warning": 5 - }, - "issue_open_num": 10, # 本次扫描新发现问题数 - "issue_fix_num": 2 # 本次扫描关闭存量问题数 - }, - "total": { # 当前项目整体信息 - "state_detail": { # 不同处理状态的问题数,包含 active(1-活跃)、resolved(2-已处理)、closed(3-已关闭) - "active": 197, - "resolved": 13, - "closed": 23297 - }, - "category_detail": { # 不同分类下不同处理状态的问题量 - "convention": { - "active": 184, - "resolved": 13, - "closed": 21143 - }, - "other": { - "active": 13, - "closed": 154 - }, - "correctness": { - "closed": 1997 - }, - "performance": { - "closed": 3 - } - }, - "severity_detail": { # 不同严重级别下不同处理状态的问题量 - "error": { - "active": 157, - "resolved": 11, - "closed": 20113 - }, - "warning": { - "active": 40, - "resolved": 2, - "closed": 2930 - }, - "info": { - "closed": 254 - } - } - }, - "status": 0, # 扫描状态,0表示成功 - "text": "成功", - "description": null, - "scan_summary": { # 扫描概览 - "convention": { - "error": { - "rule_count": 7, # 规则数 - "active": 65 # 活跃问题数 - }, - "warning": { - "rule_count": 2, - "active": 5 - } - }, - "other": { - "error": { - "rule_count": 1, - "active": 4 - } - } - }, - "total_summary": { - "correctness": { - "error": { - "rule_count": 16, - "closed": 1315 - }, - "warning": { - "rule_count": 10, - "closed": 629 - }, - "info": { - "rule_count": 1, - "closed": 53 - } - }, - "performance": { - "warning": { - "rule_count": 1, - "closed": 3 - } - }, - "convention": { - "error": { - "rule_count": 42, - "active": 149, - "resolved": 11, - "closed": 18778 - }, - "warning": { - "rule_count": 17, - "active": 35, - "resolved": 2, - "closed": 2298 - }, - "info": { - "rule_count": 1, - "closed": 67 - } - }, - "other": { - "error": { - "rule_count": 2, - "active": 8, - "closed": 20 - }, - "warning": { - "rule_count": 1, - "active": 5 - }, - "info": { - "rule_count": 3, - "closed": 134 - } - } - } - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量圈复杂度结果概览 -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/cycscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "min_ccn": 20, - "over_cc_func_count": 6, - "under_cc_func_count": 796, - "diff_over_cc_func_count": 0, - "over_cc_func_average": 22.333333333333332, - "cc_func_average": 2.5099750623441395, - "over_cc_sum": 14, - "cc_average_of_lines": 1.0422094841063054 - }, - "custom_summary": null, - "created_time": "2021-03-11T20:48:59.976947+08:00", - "creator": null, - "modified_time": "2021-03-11T20:49:00.088841+08:00", - "modifier": null, - "deleted_time": null, - "deleter": null, - "last_revision": "last_revision", - "diff_cc_num": 0, - "cc_open_num": 6, - "cc_average_of_lines": 1.0422094841063054, - "cc_fix_num": 0, - "worse_cc_file_num": 0, - "min_ccn": 20, - "code_line_num": 13433, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量重复代码结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/dupscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "default_summary": { - "exhi_risk": { - "range": [ - 0.2, - 1 - ], - "file_count": 1, - "diff": { - "diff_file_count": 0 - } - }, - "high_risk": { - "range": [ - 0.11, - 0.2 - ], - "file_count": 3, - "diff": { - "diff_file_count": 0 - } - }, - "midd_risk": { - "range": [ - 0.05, - 0.11 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - }, - "low_risk": { - "range": [ - 0, - 0.05 - ], - "file_count": 2, - "diff": { - "diff_file_count": 0 - } - } - }, - "custom_summary": null, - "last_revision": "last_revision", - "duplicate_file_count": 8, - "duplicate_block_count": 55, - "duplicate_line_count": 1177, - "diff_duplicate_block_count": 0, - "diff_duplicate_line_count": 0, - "close_issue_count": 0, - "new_issue_count": 0, - "reopen_issue_count": 5, - "ignored_issue_count": 0, - "duplicate_rate": 4.98, - "unique_duplicate_line_count": 1083, - "total_duplicate_line_count": 1083, - "total_line_count": 21745, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看项目代码度量代码统计结果概览 - -``` -GET /server/analysis/api/orgs//teams//repos//projects//overview/clocscans/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_time_before | str | 扫描任务起始时间,格式: 2021-01-01 00:00:00 | -| scan_time_after | str | 扫描任务结束时间 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "scan_revision": "scan_revision", - "scan_time": "2021-03-11T20:46:44.171607+08:00", - "last_revision": "last_revision", - "code_line_num": 140490, - "comment_line_num": 5410, - "blank_line_num": 3408, - "total_line_num": 149308, - "add_code_line_num": 6673, - "add_comment_line_num": 2309, - "add_blank_line_num": 1289, - "add_total_line_num": 10271, - "mod_code_line_num": 965, - "mod_comment_line_num": 297, - "mod_blank_line_num": 0, - "mod_total_line_num": 1262, - "del_code_line_num": 35844, - "del_comment_line_num": 2117, - "del_blank_line_num": 1794, - "del_total_line_num": 39755, - "scan": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - diff --git "a/web/packages/tca-document/zh/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" "b/web/packages/tca-document/zh/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" deleted file mode 100644 index b18030f49..000000000 --- "a/web/packages/tca-document/zh/api/\351\241\271\347\233\256\347\256\241\347\220\206\346\250\241\345\235\227\346\216\245\345\217\243.md" +++ /dev/null @@ -1,763 +0,0 @@ -# 项目管理模块 - -## 查看指定代码库的指定分支项目列表 - -``` -GET /server/main/api/orgs//teams//repos/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scm_url_or_name | str | 代码库地址或者名称,支持模糊匹配 | -| scm_url | str | 代码库仓库匹配| -| scope | str | 过滤范围(my/subscribed/related_me),my表示我创建的,subscribed表示我关注的,related_me表示我有权限的 | - -#### 返回结果 -```JSON -{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "name": "test_repo.git", - "scm_url": "http://git.com/xxx/test_repo", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-03-15 02:26:31.423674+00:00", - "recent_active": { - "id": 1, - "branch_name": "master", - "active_time": "2021-03-15T03:14:56.760427Z", - "total_line_num": null, - "code_line_num": null - }, - "created_from": "codedog_web", - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "symbol": null - } - ] -} -``` - -## 查看指定代码库详情 - -``` -GET /server/main/api/orgs//teams//repos// -``` - -#### 返回结果 -```JSON -{ - "data":{ - "id": 1, - "name": "test_repo.git", - "scm_url": "http://git.com/xxx/test_repo", - "scm_type": "git", - "branch_count": 1, - "scheme_count": 1, - "job_count": 1, - "created_time": "2021-03-15 02:26:31.423674+00:00", - "recent_active": { - "id": 1, - "branch_name": "master", - "active_time": "2021-03-15T03:14:56.760427Z", - "total_line_num": null, - "code_line_num": null - }, - "created_from": "codedog_web", - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "symbol": null - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 查看指定代码库的不同分支的列表接口 - -``` -GET /server/main/api/orgs//teams//repos//branches/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "branch": "master", - "schemes": [ - { - "project_id": 1, - "scan_scheme_id": 1, - "scan_scheme_name": "默认" - } - ] - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的分支项目列表 - -``` -GET /server/main/api/orgs//teams//repos//projects/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| branch | str | 分支名称 | -| scan_scheme | int | 扫描方案名称 | -| scan_scheme__status | int | 扫描方案状态,1为活跃,2为废弃 | -| branch_or_scheme | str | 分支名称/扫描方案名称 | -| status | int | 项目状态筛选,1表示活跃,2表示失活,3表示关闭 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "codedog_web", - "repo": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 创建指定代码库的指定分支项目 - -``` -POST /server/main/api/orgs//teams//repos//projects/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| scan_scheme_id | int | 当前代码库的扫描方案编号 | -| global_scheme_id | int | 扫描方案模板编号 | -| custom_scheme_name | str | 自定义方案名称 | -| branch | str | 分支 | -| created_from | str | 创建渠道,用于区分不同运行场景 | - -#### 返回结果 -```JSON -{ - "data": { - "id":1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "repo": { - "id": 1, - "name": "test_demo.git", - "scm_url": "http://github.com/xxxx/test_demo.git", - "scm_type": "git", - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "1", - "scm_platform": 1, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - } - }, - "auth_type": "ssh_token", - "created_time": "2021-01-28T10:26:31.453389+08:00", - "modified_time": "2021-01-28T10:26:31.453417+08:00" - }, - "symbol": null - }, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "tca_web" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的指定分支项目 - -``` -GET /server/main/api/orgs//teams//repos/// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id":1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.256015+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.256284+00:00", - "deleter": null, - "deleted_time": null, - "repo": { - "id": 1, - "name": "test_demo.git", - "scm_url": "http://github.com/xxxx/test_demo.git", - "scm_type": "git", - "scm_auth": { - "id": 1, - "scm_account": null, - "scm_oauth": null, - "scm_ssh": { - "id": 1, - "name": "1", - "scm_platform": 1, - "scm_platform_desc": null, - "user": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - } - }, - "auth_type": "ssh_token", - "created_time": "2021-01-28T10:26:31.453389+08:00", - "modified_time": "2021-01-28T10:26:31.453417+08:00" - }, - "symbol": null - }, - "scan_scheme": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme_info": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "webhook_flag": false, - "issue_revision_merge_flag": false, - "status": 1, - "scheme_key": null, - "repo": 1 - }, - "branch": "master", - "status": 1, - "created_from": "tca_web" - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的扫描方案列表 -``` -GET /server/main/api/orgs//teams//repos//schemes/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| name | str | 扫描方案名称 | -| status | int | 扫描方案状态,1为活跃,2为废弃 | - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "issue_revision_merge_flag": false, - "status": 1, - "repo": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 查看指定代码库的指定扫描方案 -``` -GET /server/main/api/orgs//teams//repos//schemes//basicconf/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "creator": { - "username": "username", - "nickname": "nickname", - "status": 1, - "avatar": null, - "org": 1 - }, - "created_time": "2021-01-28 02:27:26.209661+00:00", - "modifier": null, - "modified_time": "2021-01-28 02:27:26.255023+00:00", - "deleter": null, - "deleted_time": null, - "languages": [ - "python" - ], - "tag": "TCA_Linux", - "refer_scheme": null, - "name": "默认", - "description": null, - "default_flag": true, - "created_from": "web", - "job_runtime_limit": 600, - "ignore_merged_issue": false, - "ignore_branch_issue": null, - "ignore_submodule_clone": false, - "ignore_submodule_issue": true, - "issue_global_ignore": false, - "daily_save": false, - "lfs_flag": null, - "issue_revision_merge_flag": false, - "status": 1, - "repo": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 更新指定代码库的指定方案 -``` -PUT /server/main/api/orgs//teams//repos//schemes//basicconf/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| languages | list | 代码语言 | -| tag | str | 执行标签,目前只支持 CodeDog_Linux | -| name | str | 方案名称 | -| description | str | 方案描述 | -| default_flag | bool | 默认方案标志,一个代码库只能有一个默认方案 | -| job_runtime_limit | int | 任务执行超时时间,默认为600分钟 | -| ignore_merged_issue | bool | 忽略合入的问题 | -| ignore_branch_issue | str | 过滤参考分支引入的问题 | -| ignore_submodule_clone | bool | 不拉取子模块扫描,True表示不拉取,False表示拉取 | -| ignore_submodule_issue | bool | 忽略子模块引入的问题,True表示忽略,False表示不忽略 | -| issue_global_ignore | bool | 问题全局忽略 | -| daily_save | bool | 每次扫描原始数据存储,默认存储7天 | -| lfs_flag | bool | 拉取lfs模块开关 | -| issue_revision_merge_flag | bool | "是否开启Issue按引入版本号聚合开关 | -| status | int | 方案状态,1表示活跃,2表示废弃| - -#### 返回结果 -同[查看指定代码库的指定扫描方案](查看指定代码库的指定扫描方案)的返回结果一致 - - -## 查看指定代码库的扫描方案的代码扫描配置 -``` -GET /server/main/api/orgs//teams//repos//schemes//lintconf/ -``` -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "enabled": true, - "checkprofile": { - "id": 1, - "profile_type": 1, - "custom_checkpackage": 1, - "checkpackages": [ - 1 - ] - }, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - - -## 更新指定代码库的指定方案的代码扫描配置 -``` -PUT /server/main/api/orgs//teams//repos//schemes//lintconf/ -``` - -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| enabled | bool | 是否开启代码扫描 | - -#### 返回结果 -同[指定代码库的指定方案的代码扫描配置](指定代码库的指定方案的代码扫描配置)的返回结果一致 - -## 查看指定代码库的扫描方案的代码度量配置 -``` -GET /server/main/api/orgs//teams//repos//schemes//metricconf/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "cc_scan_enabled": false, - "min_ccn": 20, - "dup_scan_enabled": false, - "dup_block_length_min": 120, - "dup_block_length_max": null, - "dup_min_dup_times": 2, - "dup_max_dup_times": null, - "dup_min_midd_rate": 5, - "dup_min_high_rate": 11, - "dup_min_exhi_rate": 20, - "dup_issue_limit": 1000, - "cloc_scan_enabled": false, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 更新指定代码库的指定方案的代码度量配置 -``` -PUT /server/main/api/orgs//teams//repos//schemes//metricconf/ -``` - -#### 参数列表 - -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| cc_scan_enabled | bool | 圈复杂度扫描开关 | -| min_ccn | int | 最小圈复杂度 | -| dup_scan_enabled | bool | 重复代码扫描开关 | -| dup_block_length_min | int | 重复块最小长度 | -| dup_block_length_max | int | 重复块最大长度 | -| dup_max_dup_times | int | 最大重复次数 | -| dup_min_midd_rate | int | 中风险最小重复率 | -| dup_min_high_rate | int | 高风险最小重复率 | -| dup_min_exhi_rate | int | 极高风险风险最小重复率 | -| dup_issue_limit | int | 上报重复代码块数上限 | -| cloc_scan_enabled | boolean | 代码统计扫描开关 | - -#### 返回结果 -同[指定代码库的指定方案的代码度量配置](指定代码库的指定方案的代码度量配置)的返回结果一致 - -## 查看指定代码库的扫描方案的过滤路径列表 -``` -GET /server/main/api/orgs//teams//repos//schemes//scandirs/ -``` - -#### 返回结果 -```JSON -{ - "data": { - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": 1, - "dir_path": "test/*", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 1 - } - ] - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 创建指定代码库的指定方案的过滤路径列表 -``` -POST /server/main/api/orgs//teams//repos//schemes//scandirs/ -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| dir_path |str | 指定过滤路径 | -| path_type | int | 路径格式,1表示通配符,2表示正则表达式,默认为通配符 | -| scan_type | int | 扫描类型,1表示包含,2表示排除 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 13, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 36 - }, - "code": 0, - "msg": "请求成功", - "status_code": 201 -} -``` - - -## 查看指定代码库的扫描方案的指定过滤路径 -``` -GET /server/main/api/orgs//teams//repos//schemes//scandirs// -``` - -#### 返回结果 -```JSON -{ - "data": { - "id": 1, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 1 - }, - "code": 0, - "msg": "请求成功", - "status_code": 200 -} -``` - -## 更新指定代码库的指定方案的指定过滤路径 -``` -PUT /server/main/api/orgs//teams//repos//schemes//scandirs// -``` -#### 参数列表 -| 参数 | 类型 | 描述 | -| --- | --- | --- | -| dir_path |str | 指定过滤路径 | -| path_type | int | 路径格式,1表示通配符,2表示正则表达式,默认为通配符 | -| scan_type | int | 扫描类型,1表示包含,2表示排除 | - -#### 返回结果 -```JSON -{ - "data": { - "id": 13, - "dir_path": "test/*.py", - "path_type": 1, - "scan_type": 1, - "scan_scheme": 36 - }, - "code": 0, - "msg": "请求成功", - "status_code": 201 -} -``` - -## 删除指定代码库的指定方案的指定过滤路径 -``` -DELETE /server/main/api/orgs//teams//repos//schemes//scandirs// -``` - -#### 返回结果 -无 diff --git a/web/packages/tca-document/zh/community/changelog.md b/web/packages/tca-document/zh/community/changelog.md deleted file mode 100644 index e3fd99512..000000000 --- a/web/packages/tca-document/zh/community/changelog.md +++ /dev/null @@ -1,106 +0,0 @@ -# 更新日志 - -## V1.2.0 (2022-4-27) - -### Features - -- 【Web端】增加工具管理 -- 【工具】增加logback检查的安全规则 -- 【服务端】增加TCA server&web 一键部署脚本 -- 【服务端】删除main部分异步任务;调整server nginx启动位置 -- 【服务端】增加server健康监测 - -### Docs - -- 完善部署和Q&A文档 -- 上传工具列表 - -## V1.1.3 (2022-4-18) - -### Features - -- 【工具】上传开源合规检查规则 -- 【工具】新增PHP安全相关规则 -- 【服务端】上线license鉴权 -- 【客户端】支持对工具license校验 - -### Docs - -- 更新文档内的工具默认路径 -- 增加任务分布式执行能力操作文档 -- 增加PR操作流程 - -## V1.1.2 (2022-4-2) - -### Features - -- 【服务端】优化部署构建脚本 - -### Docs - -- 简化前端部署脚本&文档 -- 优化指引文档 - -## V1.1.1 (2022-3-31) - -### Features - -- 【工具】增加0daychecker工具 -- 【工具】增加Log4j、LogBack漏洞检查规则包 - -### Docs - -- 完善部署文档说明,推荐使用Docker-Compose 2.3.3版本 - -## V1.1.0 (2022-3-29) - -### Features - -- 【客户端】client支持arm64架构执行环境 -- 【客户端】client新增分布式节点模式 -- 【客户端】修改参数isTotal(是否开启全量扫描)判断方式及参数startCommand(启动客户端命令)拼接方式 -- 【服务端】支持任务分布式下发 -- 【服务端】完善基于minio的文件存储配置 -- 【Web端】调整文件资源引用地址 -- 【Web端】web模块部署脚本问题修复及优化 -- 【Web端】增加管理后台、增加在线分析 -- 【Web端】调整前端部署脚本,支持传递nginx配置地址、前端资源部署地址 - -### Bugfixes - -- Jenkins插件命令拼装逻辑修正 - -### Docs - -- 调整pypi下载失败提示 -- 调整前端部署文档及脚本 -- 更新License - -## V1.0.1 (2022-03-01) - -### Features - -- feat: 【服务端】调整代码库登记ssh url链接格式适配 -- feat: 【工具】上线支持PHP安全工具-Rips -- feat: 【工具】调整androidlint部分规则描述 -- feat: 【客户端】上线Jenkins插件 -- feat: 【客户端】增加工具拉取可选配置项 -- feat: 【客户端】支持在命令行参数中输入团队编号和项目名称 -- feat: 【客户端】限制PYTHON_VERSION环境变量可选值 -- feat: 【客户端】增加在docker中快速使用client的方式 - -### Bugfixes - -- fix: 【服务端】补充缺失的依赖 -- fix: 【Web端】修复下载codedog.ini失败提示 - -### Docs - -- doc: 上线部署文档Q&A -- doc: 优化部署文档、帮助文档说明 -- doc: 增加产品白皮书 -- doc: 补充redis和nginx源码安装参考文档 - -## V1.0.0 - -初始发布 diff --git a/web/packages/tca-document/zh/community/contribute.md b/web/packages/tca-document/zh/community/contribute.md deleted file mode 100644 index 62e870ba1..000000000 --- a/web/packages/tca-document/zh/community/contribute.md +++ /dev/null @@ -1,46 +0,0 @@ -# 贡献指南 - -欢迎报告Issue或提交Pull Request。建议在贡献代码前先阅读以下贡献指南。 - -## 报告问题 - -我们使用[Github Issues](https://github.com/Tencent/CodeAnalysis/issues)来跟踪漏洞和功能请求。 - -### 搜索已知issue - -在您提交新的issue前,请搜索现有issue以查看是否已有人提交任何类似问题或功能请求,确认不存在重复的issue。 - -### 报告新issue - -当您提交新的issue时,请尽量提供更多的信息,例如与问题相关的详细描述、屏幕截图、视频、logcat和导致崩溃的代码块。 - -## Pull Request - -我们非常欢迎您提出Pull Request来帮助TCA变得更好,操作流程详见[PullRequests操作流程](./pr.md)。 - -### 分支管理 - -TCA有两个主要分支: - -- `main` 分支: - 1. 它是最新的(预)发布分支。我们以 `main` 作为标签, 带有版本号 `v1.0.1`, `v1.0.2` ... - 2. **请不要在 `main` 分支提交任何PR.** -- `dev` 分支: - 1. 这是我们稳定发展的分支。经过全面测试后, `dev` 分支将合并到 `main` 分支的下一个版本。 - 2. **请您将修复漏洞或开发新功能的PR提交到 `dev` 分支。** - -### 提交Pull Request - -代码团队将监控所有拉取请求,我们对其进行一些代码检查和测试。在所有测试通过后,我们将接受此PR。但它不会立即合并到 `main` 分支,这有一些延迟。 - -在提交拉取请求之前,请确保完成以下工作: - -1. Fork [TCA仓库](https://github.com/Tencent/CodeAnalysis/blob/main/CONTRIBUTING.md),并从 `main` 创建分支。 -2. 如果您更改了API,请更新代码或文档。 -3. 将版权声明添加到您添加的任何新文件的顶部。 -4. 检查您的代码样式。 -5. 测试您的代码,确保其可以正常运行。 -6. 现在,您可以向 `dev` 分支提交Pull Request。 - -## 许可 -[MIT LICENSE](https://github.com/Tencent/CodeAnalysis/blob/main/LICENSE) 是 TCA 的开源许可证。任何人贡献的代码都受此许可证保护。在贡献代码之前,请确保您可以接受许可。 \ No newline at end of file diff --git a/web/packages/tca-document/zh/community/joingroup.md b/web/packages/tca-document/zh/community/joingroup.md deleted file mode 100644 index 1b3c25b08..000000000 --- a/web/packages/tca-document/zh/community/joingroup.md +++ /dev/null @@ -1,7 +0,0 @@ -# 加入社区 - -如果您需要有关TCA的帮助,希望与TCA开发者们相互认识和交流,欢迎通过以下渠道加入TCA社区! - -- 微信公众号:「腾讯云静态分析」,关注并发送“进群”即可加入官方开源交流微信群 -- QQ交流群:361791391 -- [GitHub讨论区](https://github.com/Tencent/CodeAnalysis/discussions) \ No newline at end of file diff --git a/web/packages/tca-document/zh/community/pr.md b/web/packages/tca-document/zh/community/pr.md deleted file mode 100644 index 1c0fc8852..000000000 --- a/web/packages/tca-document/zh/community/pr.md +++ /dev/null @@ -1,51 +0,0 @@ -![Welcome](../../images/Welcome.png) - -PR全称为Pull Request,它是一种代码库的协作方式。开发者可以通过PR将自己在代码库的修改通知到代码库负责人,由原作者评审代码并决定是否能合入。 - -:::tip -Pull requests let you tell others about changes you've pushed to a branch in a repository on GitHub. Once a pull request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits before your changes are merged into the base branch. -::: - -# PR操作流程 - -## 一、Fork目标代码库 - -![fork](../../images/Fork.png) - -点击Fork后,会在自己名下产生一个相同代码库,比如我Fork CodeAnalysis项目后,会在我名下多出一个CodeAnalysis代码库,地址为 - -## 二、克隆Fork的代码库并创建分支 - -在本地克隆Fork的代码库并创建分支 - -```bash -git clone https://github.com/Lingghh/CodeAnalysis -git checkout -b dev/add_qa_20220301 -``` - - 注:也可以在自己Fork的代码库GitHub页面上创建分支。 - - ![fork1](../../images/fork1.png) - - 接下来就可以在本地修改代码,修改完成后先push到Fork的代码库中. - -## 三、在目标项目中提交PR - -### 1.进入到目标项目中,点击Pull requests Tab,再点击New pull request就会进入到创建PR的页面 - -![New pull request](../../images/NewPullRequest.png) - -### 2.进入PR页面后 - -- 点击compare across forks 。 -- 点击head repository 。 -- 选择自己Fork的代码库和比较的分支,比如我这里选择Lingghh/CodeAnalysis和待合入的分支dev/add_arm64_file 。 -- 最后确认commits和changed files是否准确,如果没有问题就可以点击Create pull request 。 - - ![PR](../../images/PR.png) - -PR创建后,代码库管理员会评审你提交的代码,并决定是否接受该PR。 - -## 更多信息请参阅[GitHub PullRequest官方文档](https://docs.github.com/cn/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests/) - -## TCA团队诚邀您的加入 diff --git a/web/packages/tca-document/zh/guide/README.md b/web/packages/tca-document/zh/guide/README.md deleted file mode 100644 index 7c9c9ea9e..000000000 --- a/web/packages/tca-document/zh/guide/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# 腾讯云代码分析 - -**腾讯云代码分析**(**Code Analysis, TCA**)起步于 2012 年(内部代号CodeDog),是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。 - -用心关注每行代码迭代、助力传承卓越代码文化! - -精准跟踪管理代码分析发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码,以及度量代码复杂度、重复代码、代码统计。 - -代码分析是通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行分析,验证代码是否满足**规范性**、**安全性**、**可靠性**、**可维护性**、**部分性能**等,对代码进行综合分析和度量等指标的一种代码分析技术。 - -## 主要功能 - -### 代码检查 - -通过代码检查精准跟踪管理发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码等。 - -目前已集成众多自研、知名开源分析工具,并采用了分层分离架构,可以满足团队快速自助管理工具。 - -### 代码度量 - -包含代码圈复杂度、代码重复率和代码统计等度量信息。 - -#### 代码圈复杂度 - -圈复杂度也称为条件复杂度或循环复杂度,它可以用来衡量一个模块判定结构的复杂程度。圈复杂度大说明程序代码的判断逻辑复杂,可能造成代码质量低下且难于测试和维护。 - -定期分析工程项目中代码的圈复杂度,可以有效地帮助开发与测试逐步优化代码质量。 - -#### 代码重复率 - -定期分析工程项目中的重复代码,可以有效地帮助开发发现冗余代码,进行代码抽象和重构,降低代码风险,以便于更好的管理和维护代码。 - -#### 代码统计 - -支持全量增量展示代码行数统计,包含代码行、注释行和空白行,可以有效地跟踪了解工程项目中代码量持续变化,并可以查看各个语言的占比情况。 diff --git a/web/packages/tca-document/zh/guide/web/deploySource.md b/web/packages/tca-document/zh/guide/web/deploySource.md deleted file mode 100644 index a171c258c..000000000 --- a/web/packages/tca-document/zh/guide/web/deploySource.md +++ /dev/null @@ -1,28 +0,0 @@ -# VM 部署文档 - -## 前置条件 - -1. Linux 环境 - -2. 系统已安装 nginx - -3. TCA Server 服务已部署完毕,具备后端服务地址 - -## 部署步骤 - -1. **进入前端部署源码目录** - - 进入web服务目录,并切换至`tca-deploy-source`目录,将其视为工作目录(假设工作目录为 `/data/CodeAnalysis/web/tca-deploy-source`) - -2. **部署/更新前端服务** - - ```bash - # 部署、更新都使用此命令 - sh ./scripts/deploy.sh init -d - ``` - - 具体请查阅部署脚本内容,可根据业务调整配置。 - -3. **额外说明** - - `tca-deploy-source/scripts/config.sh` 已配置默认环境变量,用户可根据需要调整环境变量再部署前端服务,具体可查阅脚本内容。 diff --git a/web/packages/tca-document/zh/guide/web/web.md b/web/packages/tca-document/zh/guide/web/web.md deleted file mode 100644 index 6cdd73816..000000000 --- a/web/packages/tca-document/zh/guide/web/web.md +++ /dev/null @@ -1,65 +0,0 @@ -# TCA Web - -## 工程结构 - -TCA Web 采用 [Lerna](https://www.lernajs.cn/) 进行 `monorepo` 管理。 - -:::tip -[Lerna GitHub地址](https://github.com/lerna/lerna) - -[Lerna 中文命令文档](http://www.febeacon.com/lerna-docs-zh-cn/) -::: - -由 `framework`、`login`、`tca-layout`、`tca-analysis`、`tca-manage`微前端以及`tca-document`前端帮助文档组成。 - -### packages 目录说明 - -- `shared`: 公共模块 - -- `framework`: 微前端基座 - -- `login`: 登录微前端 - -- `tca-layout`: 腾讯云代码分析layout微前端 - -- `tca-analysis`: 腾讯云代码分析analysis微前端 - -- `tca-manage`: 腾讯云代码分析后台管理微前端 - -- `tca-document`: 腾讯云代码分析帮助文档 - -## 基于构建后资源部署(tca-deploy-source) - -已将当前版本各个微前端构建打包到此目录,可通过阅读该目录下的 **README** 直接进行前端部署。 - -## 基于开发模式启动 - -- 按上一节完成一套 **TCA Web** 部署 - -- 根据要调整的内容,启动对应的微前端(login、tca-layout、tca-analysis),具体可进入不同 `package` 参考阅读其目录下的 `README` 进行开发。 - -**其他**: - -- **根目录下启动单个项目** - - ```bash - # framework - yarn dev --scope framework - # login - PUBLIC_PATH=http://127.0.0.1:5055/ yarn dev --scope login - # tca-layout - PUBLIC_PATH=http://127.0.0.1:5056/ yarn dev --scope tca-layout - # tca-analysis - PUBLIC_PATH=http://127.0.0.1:5057/ yarn dev --scope tca-analysis - # tca-manage - PUBLIC_PATH=http://127.0.0.1:5058/ yarn dev --scope tca-manage - # tca-document - yarn dev --scope tca-document - # 或进入对应项目内,查阅对应README - ``` - -## 本地开发后构建部署 - -- 如对项目进行变更,本地开发结束后,需要部署最新资源可通过执行 `sh build-source.sh` 将构建后资源更新到**tca-deploy-source** 目录内,再参考该目录下的 **README** 直接进行前端更新/重新部署操作。 - -- 可通过阅读 `build-source.sh` 内容,以及 **tca-deploy-source** 目录下的 **README**,用户可根据需要自行进行前端部署。 diff --git "a/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" "b/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" deleted file mode 100644 index 591f45c64..000000000 --- "a/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\345\210\206\346\236\220\347\273\223\346\236\234\346\237\245\347\234\213.md" +++ /dev/null @@ -1,31 +0,0 @@ -# 代码检查结果查看 - -客户端分析完毕后,如果分析方案含有代码检查功能,则代码分析结束后会上报结果信息到腾讯云代码分析平台,用户可在平台上查看问题列表及详情。 - -![问题列表](../../../images/codelint_01.png) - -## 问题列表 - -进入代码检查问题列表页面后,默认展示**当前分支 + 当前分析方案(即分支项目)**发现的全部未处理问题。 - -如果仅希望查看增量问题,可以进入分析历史页面,指定查看某一次的扫描结果即可。也可以在过滤筛选项中填入发现问题的扫描 `id`进行筛选查看结果(该`id`为扫描任务 ID,需要到扫描任务列表中查询)。 - -- **责任人说明** - - 责任人为 `git blame`操作得到的代码提交人。 - -- **问题级别说明** - - 代码检查的问题级别是根据对应分析方案中规则设置的严重级别定义的,从高到低分为 **`致命、错误、警告、提示`** 。如果调整问题级别,则需要进入分析方案中调整这个规则的严重级别,调整后需要进行全量扫描使得调整生效。 - -- **批量处理说明** - - 问题列表支持批量修改问题状态。 - - ![批量处理](../../../images/codelint_02.png) - -## 问题详情 - -点击规则信息可以查看规则说明。 - -![查看规则详情](../../../images/codelint_03.png) diff --git "a/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" deleted file mode 100644 index 373c605e5..000000000 --- "a/web/packages/tca-document/zh/guide/\344\273\243\347\240\201\346\243\200\346\237\245/\346\267\273\345\212\240\350\247\204\345\210\231\351\205\215\347\275\256.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 添加规则配置 - -规则配置是代码检查应用的规则集合,用于指定用哪些工具和规则进行代码分析扫描。目前,TCA 提供了覆盖**代码规范**、**安全扫描**、**风格检查**等方面的官方推荐规则包。 - -**官方推荐规则包**是TCA长期以来在业务中实践的经验结果,将相关的有效性高的工具和规则打包在一起。业务可以根据需要选择官方推荐规则包。也可以在自定义规则包中添加希望的工具和规则。 - -::: tip -规则配置 = 自定义规则包 + 官方规则包 - -自定义规则包中的规则配置会默认覆盖其他官方包中相同规则的配置 -::: - - ![添加规则配置](../../../images/AddRule.png) - - 可以单选或者批量多选规则 - ![添加规则配置](../../../images/AddRule2.png) - -也可以根据搜索框进行多维度查询 - ![添加规则配置](../../../images/AddRule3.png) diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" deleted file mode 100644 index 37e2f3706..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\345\272\246\351\207\217\351\205\215\347\275\256.md" +++ /dev/null @@ -1,31 +0,0 @@ -# 代码度量配置 - -## 圈复杂度 - -可以发现执行路径较多的方法,降低代码的圈复杂度,可测性更高 - -- **检测阈值** - - 默认为 20,表示当一个方法的圈复杂度超过 20 时则认为该方法为超标方法,需要被关注修改。 - - 可以根据需要调整 - -## 重复代码 - -可以发现重复的代码,避免重复代码可以让代码更简洁,更易维护 - -- **长度区间** - - 是一个区间值,默认代码中一个单词(变量/操作符)长度为 1。 - -- **重复次数** - - 是一个区间值,当一段代码重复次数达到指定区间才认为是有风险的。 - -- **上报限制** - - 限制上报的重复代码块数,可以减少开发的压力,提高修复积极性。 - -## 代码统计 - -从目录和业务纬度统计代码行数,也可以获取提交记录便于代码 Review diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" deleted file mode 100644 index 84ecfd8c1..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\347\274\226\350\257\221\351\205\215\347\275\256.md" +++ /dev/null @@ -1,123 +0,0 @@ -# 代码检查-编译配置 - -腾讯云代码分析平台支持给编译类的工具或编译型项目配置相关命令。 - -由于对代码进行编译型分析会存在安全风险,需要用户自行进行专机扫描,申购完成后可联系平台管理员进行相关配置。 - -::: tip -对于编译型语言,有些分析工具是可以通过分析编译产出的中间文件,更为准确地发现代码质量问题。 -::: - ---- - -::: warning -由于对代码进行编译型分析会存在安全风险,需要用户自行进行专机扫描(私有化版由客户自行评估即可)。 -::: - ---- - -## 编译所需环境说明(重要) - -如果配置了编译命令,则需要在具有代码执行所需的编译环境的节点上执行代码分析。即需要用户在专机上提供编译环境(针对私有化版,客户可根据业务情况选择在公共节点机、用户专机、本地节点机提供编译环境即可)。 - -如以下一些编译环境: - -- JDK 环境及版本 - -- gradle 环境 - -- cmake & make 环境 - -- visual studio 环境 - -- ... - -::: warning -如果机器有多个 JDK 或者 gradle 环境,项目编译需指定 JDK 或 gradle 版本,可以在分析方案的基础属性当中设定相应环境变量。 -::: - -## 编译配置字段说明 - -**前置命令**: - -通常是项目编译前需要执行的命令,或用于清理之前编译过程的命令,如:`make clean`, `xcodebuild clean [-optionName]`。如无需要,可以不填。 - -**编译命令**: - -项目的编译命令,具体可以**咨询该代码库所属项目的开发** - -能够使项目编译成功的编译命令,可以填写多行或用 && 连接命令。 - -::: tip -前置命令与编译命令是隔离的,即在前置命令中的操作不会对编译命令产生影响。 - -如在前置命令中 `cd src && export TEST=src`,在执行编译命令时并不会跳到`src`目录和获取`TEST`环境变量。 -::: - -## 编译配置示例 - -::: tip -咨询该代码库所属项目的开发,先确保先在本地工程根目录调试通过 -::: - -### JAVA 项目 - -**编译命令**: - -android-studio 项目编译命令示例 - -```java -gradle compileDebugSources --no-daemon -Dorg.gradle.jvmargs= -``` - -ant 项目编译命令示例 - -```java -ant build -``` - -### Object-C 项目 - -**编译命令**: - -xcodebuild 命令(确保先在本地工程根目录调试通过) - -```objectivec -xcodebuild -target dailybuildipa -configuration DailyBuild -sdk iphonesimulator -``` - -**环境变量**(分析方案-基础属性中配置): - -```bash -XCODE_VERISON=10.1 -``` - -### C/C++ 项目 - -**编译命令**: - -VS 项目编译命令示例 - -```cpp -devenv.com demo.sln /Build "Debug|Win32" -# 或 -msbuild demo.sln /t:Build /p:Configuration=DebugCopy -``` - -make 项目编译命令示例 - -```cpp -make all -``` - -### C# 项目 - -**编译命令**: - -VS 项目编译命令示例 - -```cs -devenv.com demo.sln /Build "Debug|Win32" -# 或 -msbuild demo.sln /t:Build /p:Configuration=Debug -``` diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" deleted file mode 100644 index 3dd4cf6ba..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\350\247\204\345\210\231\351\205\215\347\275\256.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 代码检查-规则配置 - -在上一节文档**代码检查配置**中我们大致已经了解规则配置主要由**官方规则包**和**自定义规则包**构成,本节将详细描述规则配置。 - -**官方规则包**是由腾讯云代码分析平台经过多年深耕,在业务中不断实践整理而出的规则集合包,然而平台有超过**10000+**的规则,有些规则并未放到官方规则包中,甚至有些规则是由用户自定义的规则。此外,有些官方规则包中的规则,对于不同的团队所需可能存在差异,因此产生了如下几种问题: - -- **在规则配置中,如何添加规则?** - -- **在规则配置中,如果将官方规则包中的规则进行调整?** - -## 在规则配置中,如何添加规则? - -添加规则存在**两种入口**: - -::: tip -无论何种,最终都是将规则添加到自定义规则包中 -::: - -- 用户可直接点击页面中的添加规则 - - ![添加规则配置](../../../images/AddRule.png) - -- 用户可点击自定义规则,进入自定义规则包后,再点击添加规则 - - ![点击自定义规则包](../../../images/scheme_codelint_02.png) - - ![添加规则](../../../images/scheme_codelint_03.png) - -在添加规则过程中,可以单选或者批量多选规则,可以根据搜索栏进行多维度查询规则 - -![添加规则配置](../../../images/AddRule2.png) - -![添加规则配置](../../../images/AddRule3.png) - -## 在规则配置中,如果将官方规则包中的规则进行调整? - -用户可以点击进入官方规则包,进入官方规则包中,对已存在的规则进行编辑。 - -::: warning -在官方规则包中对规则的任意操作,实质上是将对应规则增加到自定义规则包中进行了相关操作。 - -自定义规则包中的规则配置会默认覆盖其他官方包中相同规则的配置。 -::: - -![编辑官方规则包规则](../../../images/scheme_codelint_04.png) diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" deleted file mode 100644 index 4be078e21..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\344\273\243\347\240\201\346\243\200\346\237\245\351\205\215\347\275\256.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 代码检查配置 - -腾讯云代码分析采用业界/自研的 80+ 款工具,配置代码检查项能够有效地发现代码中存在的异味代码 - -## 规则配置 - -规则配置主要是以规则包为元素,由**官方规则包**和**自定义规则包**两部分组成。平台提供一些系列的官方规则包,覆盖规范、安全、推荐等方面。 - -用户可根据项目语言、规则包类型筛选不同的规则包,并启用/关闭规则包。 - -::: tip -用户可以根据需要选择官方规则包进行扫描,并可以在官方规则包的基础上屏蔽某些规则或者调整默认的优先级,设置指定参数。这些操作都会记录在自定义规则包中。 - -自定义规则包是提供给用户自由选择工具规则的包。官方规则包上的调整实质上会记录到自定义规则包中,当自定义规则包中的规则和官方规则包的规则发生冲突,则自定义规则包优先级更高。 -::: - -![创建项目](../../../images/scheme_codelint_01.png) - -## 编译配置 - -通过编译(代码解析和翻译过程)分析中间代码进行辅助分析,能更精准地发现更多潜在的代码问题。 diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" deleted file mode 100644 index ffb2d0958..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\210\206\346\236\220\346\226\271\346\241\210\346\250\241\346\235\277\350\257\264\346\230\216.md" +++ /dev/null @@ -1,27 +0,0 @@ -# 分析方案模版 - -为便于用户快速创建代码库进行分析,复用同类型的分析配置,平台提供了分析方案模板功能。 - -分析方案模板分为**系统方案模板**和**个人自定义方案模板**。 - -- **系统方案模板** - - **全局可用**。但是用户无法变更系统方案模板内容。如系统方案模板产生变更,需用户自行拉取最新模板内容。 - - ![同步分析方案模板配置](../../../images/scheme_template_01.png) - -- **个人自定义方案模板** - - 自定义方案模板与团队挂钩,用户可自行创建、更新、同步方案模板,以及可进行权限控制。默认自定义方案模板团队内都可见。 - - ![自定义方案模板权限管理](../../../images/scheme_template_02.png) - -分析方案模版用于在创建分析方案时作为模版参考。分析方案模版全局可用,不用和某个代码库关联。 - -## 使用说明 - -- 创建分支项目时,可选择使用分析方案模板创建。默认会根据该分析方案模板创建出一个新的分析方案,并用该方案配置进行分支项目创建。 - -- 创建分析方案时,可选择使用分析方案模板创建。 - -- 用模版生成的分析方案和模版建立关联关系,当模版和生成的方案由差异时,可以由用户选择是否同步模版的内容到方案。并可以选择拉群哪些功能模块的配置。 diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" deleted file mode 100644 index 3c28a4c40..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\345\237\272\347\241\200\345\261\236\346\200\247\351\205\215\347\275\256.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 基础属性配置 - -- **方案名称** - - 用于标示一个方案,每个方案名称都是唯一的。 - -- **分析语言** - - 用于指明该方案是针对代码库何种语言进行分析。初次创建分析方案时会根据语言初始化分析方案相关配置。 - -- **运行环境** - - - 对于客户端分析,根据客户端所在本地执行机器选择对应运行环境即可。 - - - 对于在线分析,根据项目实际情况,选取对应运行环境即可。 - - ::: tip - 在线分析时,会根据方案的运行环境,将任务分配到对应环境的节点机器上执行代码分析。 - - 需考虑项目在对应环境的节点机器上能否正常执行 - ::: - -- **环境变量** - - 每行 key-value 形式,非必填项。 - - - **可用于指定特殊编译环境**:如机器有多个 JDK 或者 gradle 环境,项目编译需指定 JDK 或 gradle 版本的可以设定相应环境变量。 - - - **可用于工具传递参数**: 如`ESLINT_MAX_OLD_SPACE_SIZE=4096`配置 Js 内存大小 - - - **可用于指定项目配置**,如`PYTHON_VERSION=2` 指定为 python2 项目 - - ::: tip - 对 Python 的分析默认采用 Python3,如果需要分析 Python2 请在环境变量中设置:PYTHON_VERSION=2 - ::: diff --git "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" "b/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" deleted file mode 100644 index a1548ffbc..000000000 --- "a/web/packages/tca-document/zh/guide/\345\210\206\346\236\220\346\226\271\346\241\210/\350\277\207\346\273\244\351\205\215\347\275\256.md" +++ /dev/null @@ -1,67 +0,0 @@ -# 过滤配置 - -## 路径过滤 - -用于设定代码分析的范围,设定后,已经开启的代码检查、代码度量各项功能都会在指定的代码范围内生效。 - -目前支持**正则表达式**和**通配符**两种类型: - -- **正则表达式** - - ```txt - 请填写相对路径(基于代码库根目录),要求匹配到文件 - 使用正则表达式格式,示例如下: - 代码根目录 - |-src - |- test - |- main_test.py - |- input_test.py - |- main.py - |-test - |- param_test.py - 匹配src/test目录:src/test/.* - 匹配根目录下的test目录:test/.* - 匹配所有_test.py后缀的文件:.*_test\\.py - 修改后,下次分析生效,需要启动一次全量分析处理历史存量问题。 - ``` - - ```txt - Include 表示只分析,如只分析 src/ 目录:src/.* - Exclude 表示只屏蔽,如要屏蔽 src/lib/ 目录:src/lib/.* - ``` - -- **通配符** - - ```txt - 请填写相对路径(基于代码库根目录),要求匹配到文件 - 使用Unix通配符格式,示例如下 - 代码根目录 - |-src - |- test - |- main_test.py - |- input_test.py - |- main.py - |-test - |- param_test.py - 匹配src/test目录:src/test/* - 匹配根目录下的test目录:test/* - 匹配所有_test.py后缀的文件:*_test.py - 修改后,下次分析生效,需要启动一次全量分析处理历史存量问题。 - ``` - - ```txt - Include 表示只分析,如只分析 src/ 目录:src/* - Exclude 表示只屏蔽,如要屏蔽 src/lib/ 目录:src/lib/* - ``` - -如果几个分析方案希望共享相同的路径过滤方案,可以通过导入导出路径配置的方式进行处理。 - -::: tip -配置更改后,下次启动分析生效 -::: - -## 问题过滤 - -- **全局 Issue 忽略状态同步** - - 仅对代码检查生效。开启后,在 Issue 页面进行全局忽略操作时,其他利用该方案分析的分支项目在发现相同 Issue 时,会同步忽略该 Issue。否则不受全局 Issue 忽略状态同步影响。 diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" deleted file mode 100644 index d2cc8fbad..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/OAuth\347\256\241\347\220\206.md" +++ /dev/null @@ -1,18 +0,0 @@ -# OAuth管理 - -- 可**创建**、**编辑**、**清除**主流代码托管平台的Oauth应用配置,为使用者提供OAuth授权支持。 - -- 支持平台及如何创建OAuth应用: - - - 腾讯工蜂:[创建 OAuth 应用程序](https://code.tencent.com/help/oauth2/) - - GitHub:[创建 OAuth 应用程序](https://docs.github.com/cn/developers/apps/building-oauth-apps/creating-an-oauth-app) - - Gitee:[创建 OAuth 应用程序](https://gitee.com/api/v5/oauth_doc#/list-item-3) - - GitLab:[创建 OAuth 应用程序](https://docs.gitlab.com/ee/integration/oauth_provider.html) - -![OAuth管理](../../../images/manage_oauth_01.png) - -![OAuth管理](../../../images/manage_oauth_02.png) - -::: tip -配置OAuth应用时,回调地址栏需填入当前TCA平台配置的域名或IP地址(如当前页面非80端口,需要显式指定端口号),作为Git平台上OAuth应用的回调地址。 -::: diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" deleted file mode 100644 index 82db6162f..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\210\206\346\236\220\350\256\260\345\275\225\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 分析记录管理 - -- 可查看平台**全部分析记录**。 - -- 可点击查阅**分析记录详情**。 - -![分析记录列表](../../../images/manage_job_01.png) \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" deleted file mode 100644 index 68a879e2b..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 团队管理 - -- 可查看平台创建的团队列表,并提供了相应筛选 - -- 可**禁用**、**恢复**团队 - -![团队列表](../../../images/manage_org_01.png) - -![团队操作](../../../images/manage_org_02.png) \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" deleted file mode 100644 index 0b62da6b1..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 工具管理 - -- 可查看**全部工具**(包含平台提供工具、团队自定义工具)。 - -- 可**查看**、**编辑**工具。 - -- 可变更工具**权限状态**。 - -![工具管理](../../../images/manage_tool_01.png) - -::: tip -工具的权限状态仅能由**平台管理员**进行变更调整,需谨慎调整 - -- **团队内可用**:即工具配置了可用团队白名单的团队可以使用该工具,默认创建工具的团队已在白名单内 - -- **全平台可用**:即不同团队都可见可用该工具 - -- **支持自定义规则,全平台可用**:即该工具不同团队都可见可用,且支持用户添加团队所需的自定义规则,该自定义规则存在团队隔离,仅团队内可以,其他团队不可使用 -::: \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" deleted file mode 100644 index b51f8f02b..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\347\224\250\346\210\267\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 用户管理 - -- 可**查看**、**编辑**、**创建**平台用户。 - -- 可配置用户的**登录密码**、**用户级别**、**超级管理员**等。 - -![用户列表](../../../images/manage_user_01.png) - -![用户编辑](../../../images/manage_user_02.png) \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" deleted file mode 100644 index 3a23e9ddc..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" +++ /dev/null @@ -1,14 +0,0 @@ -# 节点管理 - -- 可查看**常驻节点状态**,包含**公共节点**和**团队节点**。 - -- 可**查看**、**编辑**、**删除**常驻节点。 - -- 可配置节点**工具进程**。 - -- 可配置**节点标签** - -![节点管理](../../../images/manage_node_01.png) -![节点管理](../../../images/manage_node_02.png) -![节点管理](../../../images/manage_node_03.png) -![节点管理](../../../images/manage_node_04.png) \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" deleted file mode 100644 index 3f6e4fbf2..000000000 --- "a/web/packages/tca-document/zh/guide/\345\220\216\345\217\260\347\256\241\347\220\206/\351\241\271\347\233\256\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 项目管理 - -- 可查看平台创建的项目列表,并提供了提供相应筛选 - -- 可**禁用**、**恢复**项目 - -![项目列表](../../../images/manage_team_01.png) \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" deleted file mode 100644 index 274a04e62..000000000 --- "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\345\233\242\351\230\237\347\256\241\347\220\206.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 团队说明 - -![成员权限](../../../images/team_member.png) - -## 层级关系 - -**团队** > **项目** > **代码库** > **分支项目** - -您可以创建一个团队,并可以在团队中创建多个项目来进行项目区分和项目管理。可以在一个项目中创建多个代码库进行代码分析。 - -## 权限控制 - -- 团队成员分为管理员和普通成员两类。团队管理员具备团队全部权限。 - -- 项目成员分为管理员和普通成员两类。项目管理员具备项目全部权限。 - -成员权限的区分,具体点击查看[成员权限](成员权限.md) - -## 邀请团队成员 - -管理员可以通过成员管理为您的团队添加成员,通过分享邀请链接的方式邀请您的团队。 diff --git "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" "b/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" deleted file mode 100644 index d4dfc5d66..000000000 --- "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\346\210\220\345\221\230\346\235\203\351\231\220.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 成员权限 - -## 团队成员 - -![成员权限](../../../images/team_member.png) - -团队成员分为**团队管理员**和**团队普通成员**两类。 - -**团队管理员**:可以邀请其他成员加入团队,具备团队内所有权限。 - -**团队普通成员**:可以创建项目,可以访问自己有权限的项目。创建项目的人会自动成为这个项目的项目管理员。 - -## 项目成员 - -项目成员分为**项目管理员**和**项目普通成员**。 - -**项目管理员**:具备项目内全部权限。 - -**项目普通成员**:可以查看项目内的配置信息和分析结果等各项信息,并且可以启动分析,但是无其他操作权限。 diff --git "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" "b/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" deleted file mode 100644 index e9684cd13..000000000 --- "a/web/packages/tca-document/zh/guide/\345\233\242\351\230\237\347\256\241\347\220\206/\350\212\202\347\202\271\347\256\241\347\220\206.md" +++ /dev/null @@ -1,105 +0,0 @@ -# 节点与标签 - -除了使用**公共节点**执行代码分析外,团队还可以利用**团队标签**注册并使用**团队节点**。 - -## 名词释义与特点 - -- 团队节点是**团队注册并管理**的**私有**节点。 - -- 团队节点**仅会运行**当前团队所属的分析任务。 - -- 团队标签是用于关联节点机器与分析项目。 - ::: tip - 当一个分析项目在方案中配置运行环境为团队标签后,该项目创建的任务就会下发到团队标签关联的节点机器上运行 - ::: - -## 适用场景 - -1. 业务项目**不想**在公共机器上**排队**等待 - -2. 业务项目**代码比较敏感**,不能在公共机器上运行 - -3. 业务项目需要**依赖特定**的**机器环境**(比如CPU架构、操作系统等) - -4. ... - -以上场景,均可考虑使用团队节点,业务团队提供机器资源接入作为团队节点,仅分析自己业务的代码库,**保证执行效率**,**保护源码不泄漏**,**支持项目特殊依赖**等 - -## 团队节点注册 - -- 根据环境下载客户端二进制文件或拉取源码,参考[客户端](../客户端/配置说明.md)。 - -- 通过终端启动客户端: - - - 客户端二进制启动 - - ```bash - ./codepuppy start -t TOKEN --org-sid ORG_SID - ``` - - - 客户端源码启动 - - ```bash - python3 codepuppy.py start -t TOKEN --org-sid ORG_SID - ``` - - ::: tip - 1. TOKEN 可以从平台**个人中心-个人令牌**页面获取 - 2. ORG_SID 可以从**页面链接**中获取 - ::: - -## 团队节点管理 - -完成团队节点注册后,可以在当前团队下看到对应的节点信息,同时**需要进行配置** - -::: warning -- 团队节点**首次注册**时,需要手动在平台上配置**所属标签**、**节点可用性**、**工具进程**等。 -- 将节点的**节点可用性**调整为**活跃**后,运行客户端节点的终端会输出**心跳上报成功**的日志 -::: - -- 首次注册团队节点,节点状态为不可用 - - ![注册团队节点](../../../images/org_node_manager_1.png) - -- 调整后的节点 - - ![注册团队节点](../../../images/org_node_manager_2.png) - -- 配置节点关联的工具进程: - - ![配置工具进程](../../../images/org_node_process.png) - -::: tip -1. 团队节点使用的**所属标签**均为当前团队内创建的标签,可参见[团队标签管理](#团队标签管理) -2. 团队标签可以参考`CodeDog`标签为不同的系统类型(Linux、MacOS、Windows)建立标签,比如`专属标签-Linux`、`专属标签-Mac`等 -::: - -### 团队节点执行任务范围 - -::: warning 使用团队节点运行分析任务的前提 -对应分析项目使用的分析方案中,需要配置分析方案中的**运行环境**为该团队节点配置的所属标签。 -::: - -::: warning 团队节点执行的任务范围取决于该节点的负责人 -- 如果节点负责人为团队管理员,该节点可以执行当前团队所有项目的分析任务 -- 如果节点负责人为项目管理员,该节点只能运行指定项目下的分析任务 -- 如果节点负责人为部分代码库的管理员,该节点只能运行对应代码库的分析任务 -::: - - -## 团队标签管理 - -您可以创建一个团队标签,并配置到您的团队节点和您的分析方案中 - -- 创建团队标签。 - - ![创建团队标签](../../../images/org_tag_manager.png) - -- 配置团队节点所属标签。 - - ![节点配置团队标签](../../../images/org_tag_node.png) - -- 配置分析方案运行环境。 - - ![方案配置团队标签](../../../images/org_tag_scheme.png) - diff --git "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" "b/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" deleted file mode 100644 index eff0e9571..000000000 --- "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\345\270\270\351\251\273\350\212\202\347\202\271\345\210\206\346\236\220.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 常驻节点分析 - -::: tip -TCA客户端除了通过`localscan`命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。 - -和本地分析一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -## 使用场景 - -- 希望通过并行执行分析来提高分析效率 - -- 希望尽量使用公共资源或使用专机资源 - -## 前置步骤 - -公共/专有机器上具备客户端。 - -如果是开源版客户端,需要配置相关环境和依赖,可查阅[开源版客户端使用说明](配置说明.md#开源版客户端使用说明)。 - -## 常驻节点配置 - -### 配置 `config.ini` 文件 - -- 将``替换成实际的serve ip(可包含端口号)。 - -### 启动代码分析常驻节点 - -- 从TCA前端页面中获取 `token`,前往 **个人中心-个人令牌-复制Token** - - ::: tip - 作为公共节点:token需要具有超级管理员权限,如使用`CodeDog`账户的`token`。 - - 可以通过[用户管理页面](../后台管理/后台管理说明.md)查看到哪些用户是超级管理员。 - - 作为专机节点:该节点仅能分析该`token`具有权限的项目。 - ::: - -- 进入到`client`目录下,执行命令:`python3 codepuppy.py -l codepuppy.log start -t ` - -- 启动后,可以在命令行输出或`codepuppy.log`中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -### 配置节点 - -常驻节点首次启动后,需要到节点管理页面设置节点状态(默认为`不可用`),将其设置为**`活跃`**,用于接收和执行任务。 - -- 进入TCA节点管理页面。`管理入口`-`节点管理` - - 可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 - - ::: tip - 常驻节点首次启动后,需将节点状态从**不可用(失效)**状态切换到**活跃(在线)**状态 - ::: - -- 可以进入**工具进程配置**页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 - -- **节点所属标签**会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 diff --git "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" "b/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" deleted file mode 100644 index 83e6e11a4..000000000 --- "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\346\234\254\345\234\260\345\210\206\346\236\220.md" +++ /dev/null @@ -1,73 +0,0 @@ -# 本地分析 - -## 使用场景 - -- 希望在本地随时分析。 - -- 如果公共机器无法满足编译环境的情况,复用本地编译环境。 - -- 如果对代码安全有要求也推荐使用本地分析。 - -## 前置步骤 - -本地具备客户端。 - -如果是开源版客户端,需要配置相关环境和依赖,可查阅[开源版客户端使用说明](配置说明.md#开源版客户端使用说明)。 - -## 分析配置 - -### 配置客户端 `config.ini` 文件 - -将 `` 替换成实际的serve ip(可包含端口号) - -### 配置客户端 `codedog.ini` 文件 - -- `token`,必填项。从TCA前端页面中获取,前往 **个人中心-个人令牌-复制Token** - -- `org_sid`,团队编号,必填项。可以从TCA前端项目页面URL获取。 - -- `team_name`,项目名称,必填项。可以从TCA前端项目页面URL获取。 - - ```bash - # 如 - http://{域名}/t/{org_sid}/p/{team_name}/profile - ``` - -- `source_dir`,本地代码目录路径,必填项。绝对路径。 - -- 其他参数 - - 按需填写其他可选项,也可以不填,按默认配置执行 - -## 启动代码分析 - -### 源码下启动分析 - -- 进入到`client`目录下 - -- 执行命令:`python3 codepuppy.py localscan` - -### docker下启动分析 - -#### 直接使用docker运行 - -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -#### 使用docker内bash终端运行 - -- 通过以下方式,进入容器内的bash终端后,通过命令行启动client代码: -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash -# 进入容器内终端,通过命令行执行扫描 -python3 codepuppy.py localscan -``` diff --git "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" "b/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" deleted file mode 100644 index 8cbe12b5a..000000000 --- "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\246\346\203\205.md" +++ /dev/null @@ -1,26 +0,0 @@ -## 在线分析 - -在线分析即是通过Server端将分析任务注册到执行队列中,并将任务分配到平台配置的常驻节点上,在常驻节点执行分析,分析完毕后将分析结果上报入库。 - -::: tip -平台需要存在常驻节点,请查阅 [常驻节点分析](./常驻节点分析.md) - -否则任务因没有机器而无法完成分配,超时后任务会注销。 -::: - -## 客户端分析 - -客户端分析即是本地分析,可直接配置本地的客户端配置文件,或在平台上配置好对应信息后,下载配置文件,替换客户端配置问题,并启动客户端分析。分析完毕后会将数据上报入库。 - -- 下载配置文件 - - ![下载配置文件](../../../images/start_scan_03.png) - -- 替换客户端配置文件,并启动客户端分析。 - -::: tip -本地需要下载客户端,请查阅 - -- [部署与配置客户端](../../quickStarted/deployClient.md) -- [客户端使用说明文档](./本地分析.md) -::: \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" "b/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" deleted file mode 100644 index 34bd7bc6e..000000000 --- "a/web/packages/tca-document/zh/guide/\345\256\242\346\210\267\347\253\257/\351\205\215\347\275\256\350\257\264\346\230\216.md" +++ /dev/null @@ -1,158 +0,0 @@ -# TCA Client - -## 一、基础配置 - -### 1. 机器配置推荐 - -| 操作系统 | 推荐配置 | -| --------: | :------------------------------------------- | -| Linux | 8核16G内存,硬盘空间256G(可用空间不低于100G) | -| Mac | 8核16G内存,硬盘空间256G(可用空间不低于100G) | -| Windows | 8核16G内存,硬盘空间256G(可用空间不低于100G) | - -以上为推荐配置,实际情况需要考虑扫描对象代码库的大小,按实际情况增加磁盘空间。 - -### 2. 配置client/config.ini文件 - --(1)将``替换成实际的serve ip(可包含端口号)。 - --(2)国内使用github拉取网络较慢,推荐使用腾讯工蜂拉取,需要修改以下配置: - -- 修改 TOOL_CONFIG_URL= -- 前往[腾讯工蜂网站](https://git.code.tencent.com)注册账号,作为拉取工具使用(已经注册过的可以直接使用) -- 将腾讯工蜂的账号密码填写到`TOOL_LOAD_ACCOUNT`中(由于腾讯工蜂的开源仓库也要求使用账号才能拉取,所以此处必须填写账号密码) - -### 3. 配置client/codedog.ini文件(分布式节点模式无需配置) - -填写以下必填项:`token`,`org_sid`,`team_name`,`source_dir` - -| 字段名 | 填写说明 | -| --------: | :------------------------------------------- | -| `token` | 从tca页面获取,前往[个人中心]-[个人令牌]-复制Token | -| `org_sid`(团队编号) | 从tca项目概览页面URL中获取,项目概览URL格式:`http://{域名}/t/{org_sid}/p/{team_name}/profile` | -| `team_name`(项目名称) | 同上 | -| `source_dir` | 本地代码目录路径 | - -其他可选项按需填写。 - -## 二、使用docker环境快速体验 - -:::tip -适用于快速上手体验。使用docker运行,可以免去客户端环境依赖的安装,避免环境兼容性问题。 - -但是由于环境受限于docker,会无法复用本地的编译环境,部分需要编译的工具无法使用。 -::: - -### 1. 下载和安装Docker - -参考Docker官方文档:[Docker下载和安装](https://docs.docker.com/get-started/) - -### 2. 构建docker镜像 - -在`client`目录下,执行以下命令:`docker build -t tca-client .` - -### 3. 执行docker容器,扫描代码,可选以下两种方式 - -#### (1)直接使用docker运行 - -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -#### (2)使用docker内bash终端运行 - -- 通过以下方式,进入容器内的bash终端后,通过命令行启动client代码: -- 在client目录下,执行以下命令: -- (注意:按照实际情况填写`SOURCE_DIR`环境变量值) - -```bash -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash -# 进入容器内终端,通过命令行执行扫描 -python3 codepuppy.py localscan -``` - -## 三、使用本地机器环境运行 - -:::tip -适用于深度体验,可以复用本地编译环境,使用编译型代码分析工具。 - -可能会有系统环境兼容问题。 -::: - -### 1. 安装Python环境和第三方库 - -- (1) 预装Python3.7、pip,支持 `python3` 和 `pip3` 命令 -- (2) 安装依赖:`pip3 install -r client/requirements/app_reqs.pip` - -### 2. 安装第三方工具 - -- (1) 进入到`client/requirements`目录 -- (2) 在命令行中执行安装脚本`install.sh`(linux/mac环境)或`install.bat`(windows环境) - -### 3. 启动代码分析 - -- (1) 进入到`client`目录下 -- (2) 执行命令:`python3 codepuppy.py localscan` - -## 四、使用分布式节点模式执行客户端 - -:::tip - -- CA客户端除了通过`localscan`命令启动单次的代码分析,也可以作为一个分布式分析节点启动,作为常驻进程,多个节点可以分布式并行执行服务端下发的任务,提高扫描效率。 -- 和本地执行任务一样,需要先安装环境和必要的工具,并配置好服务端地址。 -::: - -### 1. 安装Python环境和第三方库 - -- (1) 预装Python3.7、pip,支持 `python3` 和 `pip3` 命令 -- (2) 安装依赖:`pip3 install -r client/requirements/app_reqs.pip` - -### 2. 安装第三方工具 - -- 进入到`client/requirements`目录 -- 在命令行中执行安装脚本`install.sh`(linux/mac环境)或`install.bat`(windows环境) - -### 3. 启动代码分析节点 - -- (1)从tca页面`个人中心`-`个人令牌`-复制Token -- (2)进入到`client`目录下,执行命令:`python3 codepuppy.py -l codepuppy.log start -t ` -- (3)启动后,可以在命令行输出或`codepuppy.log`中查看运行日志,如果未报异常,且输出`task loop is started.`,表示节点已经正常启动。 - -### 4. 配置节点 - -- 从tca页面`管理入口`-`节点管理`,可以看到当前在线的节点,可以修改节点名称、标签、负责人等信息。 -- 可以进入工具进程配置页面,对节点支持的工具进程进行管理(默认会全部勾选),未勾选的工具进程,将不会在该节点上执行。 -- 节点所属标签会与分析方案中的运行环境标签进行匹配,只有相同标签的任务才会下发到该机器节点上。 - -## 五、其他配置与用法 - -### 1. 配置使用本地工具 - -:::warning -如果由于网络原因,执行时无法从github自动拉取工具,或拉取比较慢,可以参考基础配置腾讯工蜂工具地址,或使用以下方式预先下载好工具,配置使用本地工具目录。 -::: - -- (1)下载工具配置库 `https://github.com/TCATools/puppy-tools-config.git` ,存放到 `client/data/tools`目录下(如果未生成,可先创建该目录)。 -- (2)根据当前机器操作系统,查看`puppy-tools-config`目录下的`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件,将`[tool_url]`中声明的所有工具下载到 `client/data/tools`目录下。 -- (3)填写`client/config.ini`中的配置:`USE_LOCAL_TOOL`=`True`,即可使用下载好的本地工具,不自动拉取和更新工具。 - -### 2. 使用自建git server存放工具 - -:::warning -如果自己搭建了一套git server,可以将工具配置库 `https://github.com/TCATools/puppy-tools-config.git` 以及里面声明的工具仓库,存放到自建git serevr上。 -::: - -- (1)将工具配置库 `https://github.com/TCATools/puppy-tools-config.git` 上传到自建git仓库。 -- (2)按所需的操作系统,将`puppy-tools-config`仓库下的`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件中`[tool_url]`声明的所有工具库,上传到自建git仓库。 -- (3)修改`linux_tools.ini`或`mac_tools.ini`或`windows_tools.ini`文件中`[base_value]`中的`git_url`为自建git server地址。 -- (4)修改`client/config.ini`中的`TOOL_CONFIG_URL`为自建git server的`puppy-tools-config`仓库地址。 -- (5)填写`client/config.ini`中的`[TOOL_LOAD_ACCOUNT]`配置,输入有拉取权限的用户名密码,即可使用自建git server拉取工具。 - -### 3. git lfs带宽和存储配额不够问题 - -- 如果git拉取工具时,出现git lfs拉取失败,可能是lfs带宽和存储配额不够,可以打开对应的工具github页面,通过`Download ZIP`的方式下载工具压缩包,再解压到`client/data/tools`目录下。 diff --git "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" "b/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" deleted file mode 100644 index 45082ec7f..000000000 --- "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\345\267\245\345\205\267\347\256\241\347\220\206\350\257\264\346\230\216.md" +++ /dev/null @@ -1,52 +0,0 @@ -# 工具管理说明 - -腾讯云代码分析平台目前已集成众多自研、知名开源工具,并采用分层分离的架构,可以快速对接企业内部团队研发的工具,并将其集成到平台内供企业内部团队使用,满足快速自助的管理工具。 - -- 按工具来源划分,工具包含**平台提供**的工具,以及**团队接入**的工具。 - - **平台提供工具**:由腾讯云代码分析平台提供的一系列自研、知名开源工具,此类工具都为公开工具,任何团队都可以使用此工具及工具规则进行代码分析。 - - **团队接入**:由团队自行接入的工具,默认该工具仅能在团队内使用,如需跨团队使用或任何团队都可以使用需联系平台管理员进行配置。 - -- 按工具使用划分,工具包含**可自定义规则工具**、**可使用工具**两种。 - - **可自定义规则工具**:该工具任何团队都可以使用,且该工具可以支持添加团队所需的自定义规则。如`RegexScan`工具,各个团队都可以使用该工具提供的规则,也可以自定义规则,此自定义规则团队隔离。 - - **可使用工具**:该工具团队内可使用,但不能添加自定义规则 - -::: tip -目前开源版仅**`RegexFileScan`、`RegexScan`**等两款工具支持用户自定义规则 - -需平台管理员在**后台管理**-**工具管理**中找到对应工具,并将其权限状态调整为**支持自定义规则**。 -::: - -## 自定义工具 -### 工具白名单 -默认自定义工具只能当前团队内使用,添加 `工具白名单` 后可以让其他团队使用。 - -## 使用场景说明 - -::: tip -添加工具、添加工具规则、添加自定义规则等均需团队内管理员可操作。分析。 -::: - ---- - -【用户 A1】【用户 A2】为【团队 O1】的管理员,【用户 A3】为【团队 O2】的普通成员。 - -【用户 B1】【用户 B2】为【团队 O2】的管理员,【用户 A3】为【团队 O2】的普通成员。 - -### 场景 1 - -- 【用户 A1】在工具管理页面添加了【工具 T1】,该工具为团队内工具; -【用户 A1】【用户 A2】均可操作该工具,如修改工具信息、添加工具规则等,【用户 A3】仅可以使用该工具,如在规则配置页面添加该工具规则; - -- 由于【工具 T1】目前仅【团队 O1】可用,【团队 O2】中无法看到此工具,即【团队 O2】内的成员无法使用该工具。 -- 如需【工具 T1】也让【团队 O2】使用有两种解决方法:1. 【工具 T1】将【团队 O2】加入使用白名单;2. 向平台发起申请,由平台管理员将【工具 T1】调整为全部团队都可使用。 - -### 场景 2 - -- 【用户 A3】在工具管理页面发现了可自定义规则的工具,如`正则工具 RegexScan`,进入工具-自定义规则栏,发现没有添加规则的入口; -- 由于【用户 A3】仅为普通成员权限,因此无法添加规则,此时需要【团队 O1】的管理员才能操作; -- 添加【自定义规则 R1】完成后,团队内全部成员均可使用该自定义规则,如在规则配置页面添加该自定义规则; -- 由于【自定义规则 R1】是团队隔离的,即【团队 O1】创建的自定义规则,在【团队 O2】中并看不到,且无法使用该规则; -- 如需【自定义规则 R1】也让【团队 O2】使用,则仅能向工具方发起申请,由工具方将该自定义规则调整为工具规则。 diff --git "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" "b/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" deleted file mode 100644 index 249135666..000000000 --- "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\345\267\245\345\205\267.md" +++ /dev/null @@ -1,190 +0,0 @@ -# 自定义工具 - -腾讯云代码分析平台支持用户自助添加代码分析工具。 - -适用场景:自定义规则无法满足团队业务复杂需求,需要更多的代码逻辑来匹配目标代码的情况。通常需要团队业务方自行实现对应代码分析工具。 - -只需要几步操作: - -1. 编写代码,实现扫描工具逻辑 -2. 提交工具到 git 代码库 -3. 在页面创建新工具 -4. 为工具添加规则 -5. 将工具配置到执行节点 -6. 在项目分析方案中添加规则 - -## 自定义工具步骤说明 - -### 第一步,编写代码,实现分析工具逻辑 - -根据需要匹配的目标代码场景,编写对应的工具逻辑。 -可以参考 Python 实现的 [Demo 项目](https://github.com/TCATools/demo_tool)。 - -**必要:** - -- **运行方式**:支持命令行执行,比如 python run.py 或 run.exe,执行命令的工作目录为工具代码的根目录。 - -- **运行环境说明**: - - 建议将工具打包编译成可执行程序,拉取下来直接可以执行。 - - 如果工具需要在特定的环境中运行,比如python、java环境,平台提供了丰富的工具依赖包,可以在`工具管理`-`工具依赖`中查看,创建工具时可供选择,执行时会自动配置好依赖环境。 - - 如果现有的工具依赖包未支持所需依赖,也可以创建新的工具依赖使用。 - -- **平台已提供的环境变量** - - - 获取及使用方式请参考 [Demo 项目](https://github.com/TCATools/demo_tool)。 - ``` - SOURCE_DIR:要扫描的代码目录路径 - DIFF_FILES: 值为一个json文件路径,文件内容为增量扫描的文件列表(增量扫描时可用) - SCAN_FILES: 值为一个json文件路径,文件内容为需要扫描的文件列表(增量或全量扫描均可用) - TASK_REQUEST: 值为一个json文件路径,文件内容为当前扫描任务参数 - ``` - -- **工具命令声明** - - 在工具仓库根目录下,添加一个`tool.json`文件,声明工具的检查和扫描命令,比如: - ```json - { - "check_cmd": "python src/main.py check", - "run_cmd": "python src/main.py scan" - } - ``` - 参数说明: - - `check_cmd`: - - 功能:判断当前执行环境是否满足工具要求(如果不需要检查,也可以没有这个命令)。 - 比如某些工具只能在linux下执行,需要判断当前是否为linux环境。 - - 输出:将判断结果输出到`check_result.json`文件中,文件内容为`{"usable": true}`或`{"usable": false}`。 - - `run_cmd`: - - 功能:扫描代码,执行自定义检查器逻辑(该命令必须存在)。 - - 输出:按照指定格式,输出结果到`result.json`文件中。 - -- **工具输出格式要求** - - - 将扫描结果输出到当前工作目录下的`result.json`文件中(Python 示例代码) - ```python - import json - with open("result.json", "w") as fp: - json.dump(result, fp, indent=2) - ``` - - - `result.json` 文件格式如下: - ```json - [ - { - "path": "文件绝对路径", - "line": "行号,int类型", - "column": "列号, int类型,如果工具没有输出列号信息,可以用0代替", - "msg": "提示信息", - "rule": "规则名称,可以根据需要输出不同的规则名", - "refs": [ - { - "line": "回溯行号", - "msg": "提示信息", - "tag": "用一个词简要标记该行信息,比如uninit_member,member_decl等,如果没有也可以都写成一样的", - "path": "回溯行所在文件绝对路径" - }, - ... - ] - }, - ... - ] - ``` - - **`refs`** 字段说明: - - 非必需项,可无。该字段记录问题回溯路径信息。比如当前行的代码问题,是经过上下文的三行代码执行路径而导致的,可以将这三行的位置及提示信息,按顺序添加到 refs 数组中。 - -### 第二步,提交工具到 git 代码库 - -- 创建代码库,将工具源代码或编译打包后的可执行文件,提交到代码仓库中(建议提交到master分支,TCA默认拉取的是master分支)。 - -- 建议代码库中加入 README.md 文件,说明工具功能和维护人。 - -- 后续需要修改工具实现逻辑,可以直接更新代码库,TCA 平台在执行该工具时,会自动拉取最新工具代码版本。 - -### 第三步,在工具管理页面中创建工具 - -- 进入工具管理页面,点击创建工具 - - ![enter image description here](../../../images/customtool_01.png) - -- 填写工具信息 - - ![enter image description here](../../../images/customtool_02.png) - - **部分参数说明:** - - - **工具仓库地址**,即前述步骤中提交的工具 git 代码库地址,默认拉取的是master分支,如果是其他分支,需要在仓库地址后加上`#分支名`,比如:`https://github.com/xxx/xxx.git#main` - - - **工具认证**,授权拉取工具仓库的权限 - - - **执行命令**,该命令会在工具根目录下执行 - - - **环境变量**,工具执行所需的环境变量 - - - **License**,如果是开源工具,填写工具遵循的开源协议,或者填写自研共建 - - - **是否为编译型工具**,表示在使用该工具对用户代码进行分析时,是否要求代码需要编译或可执行编译 - - -- 添加工具依赖 - - ![enter image description here](../../../images/customtool_03.png) - - 添加完成后,会展示已添加的依赖方案: - - ![enter image description here](../../../images/customtool_04.png) - -**工具依赖说明:** -- 比如当前的demo工具,只需要依赖python3运行,而且支持在linux x86_64、linux arm64、mac和windows下执行,那么只需要配置一个依赖方案(如上图),并配置为默认方案。在不同的操作系统中,会自动加载对应操作系统的python环境。 -- 如果需要根据扫描项目设置的环境变量,加载不同的依赖配置,则可以配置不同的判断条件,使用多个依赖方案。 - - -### 第四步,为工具添加规则 - -- 完成工具创建后,进入规则列表,为工具添加规则 - - ![enter image description here](../../../images/customtool_05.png) - -- 填写规则信息 - - **部分参数说明:** - - - **规则简介**:简要描述规则发现的是什么问题,扫描结果中会作为问题标题展示 - - - **详细描述**:可详细描述规则,以及规则的解决方式,建议附上解决案例 demo - - - **解决方法**:按照实际情况,说明该代码问题的解决方法,建议附上解决案例 demo - - - **规则参数**:如果不需要通过规则参数传递信息,可留空 - -### 第五步,将工具配置到执行节点 - -::: tip -需要联系平台管理员协助操作,在`管理入口`-`节点管理`中进入需要配置的机器节点的`工具进程配置`中,找到对应工具,勾选工具进程。 - -完成节点配置工具进程后,才能在项目中采用该工具进行分析。 -::: - -![enter image description here](../../../images/customtool_06.png) - -### 第六步,完成上述操作,在项目中使用工具规则 - -- 进入到项目中,在`分析方案`-`代码检查`进行规则配置。 - -- 点击添加规则,找到对应工具规则进行添加。 - -- 添加完成后,启动分析,为了将规则应用到所有代码文件,建议启动一次全量分析(增量分析只会分析自上次扫描后变更的文件)。 - -## 自定义工具权限说明 - -- **默认自定义工具仅团队管理员可操作,团队内所有成员可使用。** - - - 团队管理员才能创建工具,添加工具规则等,具备该工具全部权限 - - - 团队内所有成员可使用该工具规则,如在规则配置中添加此工具规则,团队普通成员仅只读权限 - -- **工具希望全平台使用?** - - 由于全平台使用的工具影响范围较大,建议团队先在团队内对工具进行充分测试,保障团队内工具的高有效性,如需全平台使用,需联系平台管理员进行申请 - - 平台管理员需对此工具进行审核,在确保工具的高有效性下可将此工具权限调整为全平台可使用 diff --git "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" "b/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" deleted file mode 100644 index 6912b5b43..000000000 --- "a/web/packages/tca-document/zh/guide/\345\267\245\345\205\267\347\256\241\347\220\206/\350\207\252\345\256\232\344\271\211\350\247\204\345\210\231.md" +++ /dev/null @@ -1,73 +0,0 @@ -# 自定义规则 - -自定义规则即由业务团队根据自身需求,由业务团队自行设计提供的规则。 - -## 自定义规则权限说明 - -- 工具需开放**支持自定义规则**权限,才可添加自定义规则。 - - - 当前平台提供的工具中,仅`RegexFileScan`、`RegexScan`两款工具支持使用用户自定义规则。 - - - 开放**支持自定义规则**权限,需平台管理员在**管理入口**-**工具管理**中找到对应工具,并将其权限状态调整为**支持自定义规则**。 - -- 自定义规则仅支持团队管理员添加,且默认仅团队内可见。 - - - 满足不同团队自定义规则可能存在的差异和隐私性。 - -- 如需将自定义规则加入工具默认规则,需联系工具提供方团队管理员添加。 - -## 平台提供的正则工具 RegexScan 说明 - -`正则工具 RegexScan` 即为开放了自定义规则功能的工具,可进入工具管理页面,搜索工具名称`RegexScan`,查看该工具已存在的规则以及根据团队业务需求,添加自定义规则。 - -适用场景:通过正则表达式,能够匹配到目标代码的情况。 - -### 自定义规则步骤 - -1. **根据团队业务需求设计正则表达式** - - ::: tip - 建议先测试好正则表达式是否正确,正则表达式测试网站推荐:[http://tool.oschina.net/regex](http://tool.oschina.net/regex) - - 规则示例: - - - 规则分析场景 - - 分析代码中的 usleep() 方法调用,如果参数小于 100 ,容易造成 CPU 使用率过高,造成性能浪费,判断为缺陷。 - - - 正则表达式 - - 匹配 usleep() 字符串,括号中的内容为 1 位或 2 位整数,那么正则表达式可以写成 `\busleep\s*\(\s*\d{1,2}\s*\)`,这里考虑了字符串中存在空格的情况。 - ::: - -2. **进入正则工具添加自定义规则** - - 进入工具管理页面,找到正则工具`RegexScan`,并点击进入自定义规则列表页,点击添加规则按钮。 - -3. **填写规则信息** - - **规则参数填写说明(必要):** - - 参数格式类似 ini 的格式, 也就是 key = value 的格式 - - - **【必要】** regex 参数,用于指定分析的正则表达式, 例如: `regex = \busleep\s*\(\s*\d{1,2}\s*\)`。 - - - **【必要】** msg 参数,用于展现 issue 说明, 例如: `msg = 函数方法%s 已经废弃,请使用 xxx 方法`。 - - msg 中的“%s”使用 regex 中的 group(用“()"括起来的部分)一一匹配。 - - 如果 regex 没有定义 group,则 msg 最多有一个%s, 并由整个 regex 匹配的字符串替代 - - 如果 msg 里没有包含“%s”,则直接显示 msg - - 如果 msg 没有提供,则默认为“发现不规范代码:%s”(不建议使用默认格式,太笼统) - - - **【可选填】** ignore_comment 参数,用于指定是否忽略注释代码,可选值:True、true、False、false 。例如 `ignore_comment=True`, 默认是 False - - - **【可选填】** include 参数,用于将指定分析文件匹配范围,使用 unix 的文件匹配格式,多项使用英文分号;隔开。例如 `include = path/to/dir;path/to/\*.cpp` - - - **【可选填】** exclude 参数,用于指定不分析的文件。格式参考 include 参数。 - -4. **将自定义规则添加到项目分析方案中** - - 添加完成,可在分析方案-代码检查-规则配置中添加该自定义规则 diff --git "a/web/packages/tca-document/zh/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/web/packages/tca-document/zh/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" deleted file mode 100644 index 70bdc82cd..000000000 --- "a/web/packages/tca-document/zh/guide/\345\277\253\351\200\237\345\205\245\351\227\250/\345\277\253\351\200\237\345\220\257\345\212\250\344\270\200\346\254\241\344\273\243\347\240\201\345\210\206\346\236\220.md" +++ /dev/null @@ -1,77 +0,0 @@ -# 快速启动一次代码分析 - -## 创建项目 - -- **创建团队并进入** - - ![创建团队](../../../images/create_team.png) - - :::tip - 还没有团队?点击了解[团队管理](../团队管理/团队管理.md) - ::: - -- **为团队创建一个项目,或选择一个已有项目,并进入项目内** - - ![创建项目](../../../images/create_team_group.png) - -## 完成代码库登记 - -- **完成代码库登记,并点击进入代码分析** - - ![代码库登记](../../../images/create_repo.png) - - ![进入代码分析](../../../images/start_scan_01.png) - -## 开启第一次代码分析 - -### 执行初始化创建 - - ![开始分析](../../../images/start_scan_02.png) - - ::: tip - - 1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 - 2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目,最终下载客户端分析配置文件,客户端执行代码分析。 - ::: - -### 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../../images/start_scan_06.png) - -#### 在线分析 - -在线分析即是通过Server端将分析任务注册到执行队列中,并将任务分配到平台配置的常驻节点上,在常驻节点执行分析,分析完毕后将分析结果上报入库。 - -::: tip -平台需要存在常驻节点,请查阅 [常驻节点分析](../客户端/常驻节点分析.md) - -否则任务因没有机器而无法完成分配,超时后任务会注销。 -::: - -#### 客户端分析 - -客户端分析即是本地分析,可直接配置本地的客户端配置文件,或在平台上配置好对应信息后,下载配置文件,替换客户端配置问题,并启动客户端分析。分析完毕后会将数据上报入库。 - -- 下载配置文件 - - ![下载配置文件](../../../images/start_scan_03.png) - -- 替换客户端配置文件,并启动客户端分析。 - -::: tip -本地需要下载客户端,请查阅 [客户端使用说明文档](../客户端/本地分析.md) -::: - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../代码检查/分析结果查看.md)等。 - -![分支概览](../../../images/start_scan_04.png) diff --git "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" "b/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" deleted file mode 100644 index fb93b011a..000000000 --- "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_with_minio.md" +++ /dev/null @@ -1,60 +0,0 @@ -# 基于MinIO部署文件服务器 -TCA的``file``服务支持对接``MinIO``作为底层存储,将文件转发到已部署的MinIO平台上进行持久化存储 - -## 本地部署 -> 注意:如果之前已经使用本地进行存储,切换为MinIO后,之前已经上传的文件只能到服务部署的目录``server/projects/file/data``查看,不支持通过页面进行下载 - -### 前置步骤 -获取MinIO平台登录的账号密码,用于上传文件 - -### 配置步骤 -#### 1. 调整``file``服务的配置 -修改``server/configs/django/local_file.py``文件,取消以下代码的注释 - -``` -# MINIO -STORAGE = { - "CLIENT": os.environ.get("FILE_STORAGE_CLIENT", "MINIO"), # 存储方式 - "OPTIONS": { - "MINIO_ENTRYPOINT": os.environ.get("FILE_MINIO_ENTRYPOINT"), - "MINIO_ACCESS_KEY": os.environ.get("FILE_MINIO_ACCESS_KEY"), - "MINIO_SECRET_KEY": os.environ.get("FILE_MINIO_SECRET_KEY"), - } -} -``` - -修改``server/scripts/config.sh``文件,填写MinIO的信息 - -```bash -export FILE_MINIO_ENTRYPOINT= -export FILE_MINIO_ACCESS_KEY= -export FILE_MINIO_SECRET_KEY= -``` - -修改完配置后,如果服务已经正在运行,则执行以下命令重启服务 - -```Bash -$ cd server -$ ./scripts/deploy.sh start -``` - -#### 2. 修改nginx服务的配置文件 -删除nginx已有的文件服务器配置文件``/etc/nginx/conf.d/tca_file_local.conf``文件,然后执行 - -```bash -rm /etc/nginx/conf.d/tca_file_local.conf -ln -s $CURRENT_PATH/configs/nginx/tca_file_minio.conf /etc/nginx/conf.d/tca_file_local.conf -``` - -> 也可以修改``server/scripts/init_config.sh`` ->```Bash -> # 注释这一行 -> ln -s $CURRENT_PATH/configs/nginx/tca_file_local.conf /etc/nginx/conf.d/tca_file_local.conf -> # 取消注释这一行 -> ln -s $CURRENT_PATH/configs/nginx/tca_file_minio.conf /etc/nginx/conf.d/tca_file_local.conf ->``` - -修改完配置后,如果nginx已经正在运行,则执行``nginx -s reload`` - -### 结尾 -以上两个步骤操作完成后,就可以通过``MinIO``存储文件了~ \ No newline at end of file diff --git "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" "b/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" deleted file mode 100644 index 1eef61455..000000000 --- "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/deploy_without_migrate.md" +++ /dev/null @@ -1,15 +0,0 @@ -在实际的生产环境的部署过程中,团队的MySQL的管理员可能不会给到应用账号create等比较敏感的权限,这种情况下,我们可以通过手动迁移数据的方式起到和等同Django migrate的效果。 - -操作步骤: - -1. 进入Server服务工作目录后(假设工作目录为 ``/data/CodeAnalysis/server/``,以下路径均为工作目录内的相对路径) -2. 在开发环境一个有全部权限的MySQL地址,初始化数据(MySQL版本运行版本:5.7) - - 执行``vi ./scripts/config.sh``:填写一个有全部权限的MySQL数据库地址和Redis信息以及根据需要调整配置信息,主要的工程配置已提供默认值,字段说明可以查看[文档](../server/README.md) - - 执行``bash ./scripts/deploy.sh init``:初始化DB、安装依赖和运行初始化脚本 - - 使用MySQLDump工具导出表结构与数据:``mysqldump -u user -p –databases codedog_main codedog_analysis codedog_file codedog_login > codedog_all.sql`` -3. 在生产环境建数据库,详情见:``server/sql/init.sql`` -4. 连接MySQL,导入数据: - - 临时关闭外键检查: ``SET SESSION FOREIGN_KEY_CHECKS=0``,否则会因为数据中有外键关联导致导入失败 - - 导入表结构与数据: ``source /youdir/codedog_all.sql;`` - - 开启外键检查: ``SET SESSION FOREIGN_KEY_CHECKS=1`` -5. 启动服务: 直接执行 ``bash ./scripts/deploy.sh start``,无需执行 ``init``方法,否则会导致数据重复写入 diff --git "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/server.md" "b/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/server.md" deleted file mode 100644 index 8d1b25a01..000000000 --- "a/web/packages/tca-document/zh/guide/\346\234\215\345\212\241\347\253\257/server.md" +++ /dev/null @@ -1,133 +0,0 @@ -# TCA Server - -## 工程结构 -TCA Server由Main、Analysis、Login、File、ScmProxy五个微服务组成,主要技术栈为Django+uwsgi+nginx - -## 配置说明 - -注意:以下配置内容可以参考 [config.sh](https://github.com/Faberiii/CodeAnalysis/blob/main/server/scripts/config.sh)文件进行查阅,使用时主要关注 MySQL、Redis 的配置,其他配置均已提供默认值,可以根据需要进行调整 - -### Main服务 -框架配置: - -- MAIN_DEBUG_MODE: Main服务的Debug模式,``true/false`` -- MAIN_SECRET_KEY: Main服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Main服务DB配置: - -- MAIN_DB_NAME:Main服务的数据库名称 -- MAIN_DB_USER:Main服务的数据库用户名 -- MAIN_DB_PASSWORD:Main服务的数据库密码 -- MAIN_DB_HOST:Main服务的数据库地址 -- MAIN_DB_PORT:Main服务的数据库端口号 - -Main服务Redis配置: - -- MAIN_REDIS_HOST:Main服务访问的Redis地址 -- MAIN_REDIS_PORT:Main服务访问的Redis端口号 -- MAIN_REDIS_PASSWD:Main服务访问的Redis密码 -- MAIN_REDIS_DBID:Main服务访问的Redis DB编号,默认为1(Analysis服务默认访问0号DB) - -服务交互配置: -- MAIN_SENTRY_DSN:Main服务异常日志上报至sentry配置 -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token -- FILE_SERVER_TOKEN:文件服务器访问Token -- CODEDOG_TOKEN:CodeDog默认访问的Token - - -### Analysis服务 -框架配置: - -- ANALYSIS_DEBUG_MODE: Analysis服务的Debug模式,``true/false`` -- ANALYSIS_SECRET_KEY: Analysis服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Analysis服务DB配置: - -- ANALYSIS_DB_NAME:Analysis服务的数据库名称 -- ANALYSIS_DB_USER:Analysis服务的数据库用户名 -- ANALYSIS_DB_PASSWORD:Analysis服务的数据库密码 -- ANALYSIS_DB_HOST:Analysis服务的数据库地址 -- ANALYSIS_DB_PORT:Analysis服务的数据库端口号 - -Analysis服务Redis配置: - -- ANALYSIS_REDIS_HOST:Analysis服务访问的Redis地址 -- ANALYSIS_REDIS_PORT:Analysis服务访问的Redis端口号 -- ANALYSIS_REDIS_PASSWD:Analysis服务访问的Redis密码 -- ANALYSIS_REDIS_DBID:Analysis服务访问的Redis DB编号,默认为0(Main服务默认访问1号DB) - -服务交互配置: -- ANALYSIS_SENTRY_DSN:Analysis服务异常日志上报至sentry配置 -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - - -### Login服务 -框架配置: - -- LOGIN_DEBUG_MODE: Login服务的Debug模式,``true/false`` -- LOGIN_SECRET_KEY: Login服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -Login服务DB配置: - -- LOGIN_DB_NAME:Login服务的数据库名称 -- LOGIN_DB_USER:Login服务的数据库用户名 -- LOGIN_DB_PASSWORD:Login服务的数据库密码 -- LOGIN_DB_HOST:Login服务的数据库地址 -- LOGIN_DB_PORT:Login服务的数据库端口号 - -服务交互配置: -- PASSWORD_KEY:数据加密密钥 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - -注:配置文件中的pub_key与private_key生成方式可以参考以下方法: -```bash -$ ssh-keygen -t rsa -b 1024 -m PEM -f tca_login.key -$ openssl rsa -in tca_login.key -pubout -outform PEM -out tca_login.key.pub -$ cat tca_login.key # 作为private_key的内容 -$ cat tca_login.key.pub # 作为pub_key的内容 -``` - -### File服务 -框架配置: - -- FILE_DEBUG_MODE: File服务的Debug模式,``true/false`` -- FILE_SECRET_KEY: File服务的Secret Key配置,可以通过``from django.core.management.utils import get_random_secret_key;get_random_secret_key()``方法获取 - -File服务DB配置: - -- FILE_DB_NAME:File服务的数据库名称 -- FILE_DB_USER:File服务的数据库用户名 -- FILE_DB_PASSWORD:File服务的数据库密码 -- FILE_DB_HOST:File服务的数据库地址 -- FILE_DB_PORT:File服务的数据库端口号 - -服务交互配置: -- FILE_SENTRY_DSN:File服务异常日志上报至sentry配置 -- API_TICKET_SALT:服务访问Token加密密钥 -- API_TICKET_TOKEN:服务访问Token - -File存储引擎配置 -- FILE_STORAGE_CLIENT: 文件存储引擎,可选项:``LOCAL``/``MINIO``/``COS`` - - 当配置引擎为``LOCAL``,可以指定``FILE_STORAGE_DIR``文件存放的路径 - - 当配置引擎为``MINIO``,可以指定以下变量: - - FILE_MINIO_ENTRYPOINT:MINIO服务地址 - - FILE_MINIO_ACCESS_KEY:MINIO服务访问账号 - - MINIO_SECRET_KEY:MINIO服务访问密码 - - 当配置引擎为``COS``,可以指定以下变量 - - TENCENT_COS_APPID - - TENCENT_COS_SECRETID - - TENCENT_COS_SECRETKEY - - TENCENT_COS_REGION - - TENCENT_COS_ROOT_BUCKET:填写格式为bucket-appid - -### ScmProxy -服务配置: -- SCMPROXY_HOST:ScmProxy服务的HOST,默认为``0.0.0.0`` -- SCMPROXY_PORT:ScmProxy服务监听端口,默认为``8009`` -- SCMPROXY_SENTRY_URL:ScmProxy服务异常日志上报至sentry配置 -- SCMPROXY: 通过本环境变量去指定其他服务调用ScmProxy服务的地址,默认值为``127.0.0.1:8009`` diff --git a/web/packages/tca-document/zh/quickStarted/FAQ.md b/web/packages/tca-document/zh/quickStarted/FAQ.md deleted file mode 100644 index 481d771b8..000000000 --- a/web/packages/tca-document/zh/quickStarted/FAQ.md +++ /dev/null @@ -1,387 +0,0 @@ -# 常见问题 - -:::tip -该Q&A文档会持续更新,非常欢迎您的建议与共建! - -如果您遇到任何未在此处列出的部署或使用问题,请在 GitHub issue 系统中进行搜索。如果仍未找到该错误消息,您可以通过[社区](../community/joingroup.md)提出问题,获得帮助。 -::: - -[[toc]] - -## Server常见问题与处理方法 - -### 1. 环境部署 - -#### 1.1 pypi下载超时或失败 - -如果在执行``pip install``环节出现以下错误,可以调整一下镜像源: - -```bash -WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='files.pythonhosted. org', port=443): Read timed out.(read timeout=15)") ' -``` - -该错误是访问官方``pypi``下载源时网络不通或者不稳定导致,可以通过以下方式调整: - -本地部署时,调整``pypi``下载源配置方式: - -```bash -mkdir ~/.pip/ -echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` - -Docker-Compose部署时,调整``pypi``下载源配置方式: - -```bash -vi server/dockerconfs/Dockerfile-common -``` - -调整文件中最后一行 ``RUN``指令 - -```bash -RUN mkdir -p log/ && \ - mkdir ~/.pip/ && \ - echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf && \ - pip install -U setuptools pip && \ - pip install -r requirements.txt -``` - -注:如果需要指定其他``pypi``下载源,可以将``https://mirrors.cloud.tencent.com/pypi/simple``进行替换 - -如果出现以下错误: - -```bash -WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')': /simple/setuptools/ -``` - -该错误是无法正常解析``pypi``访问域名,需要检查一下本地的dns配置是否正常 - -#### 1.2 Docker未安装或版本过低 - -TCA Server使用Docker-Compose依赖的Docker版本需要是``1.13.0``及以上,可以执行以下命令查看Docker版本 - -```bash -$ docker --version -Docker version 18.09.7, build 2d0083d -``` - -文档相关: - -- [Compose文件版本与对应的Docker版本说明文档](https://docs.docker.com/compose/compose-file/compose-versioning/) -- [CentOS安装Docker官方文档](https://docs.docker.com/engine/install/centos/) -- [Ubuntu安装Docker文档](https://docs.docker.com/engine/install/ubuntu/) - -#### 1.3 Docker-Compose启动失败 - -如果启动Docker-Compose输出以下错误: - -```bash -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -* Error response from daemon: Error processing tar file(exit status 1): unexpected EOF -``` - -问题原因:可能镜像构建目录权限不足,导致异常。 -解决方案: - -1. 执行``docker-compose build``可以通过日志查看是哪个镜像构建异常 -2. 切换到具体目录执行``docker build .``可以看到详细错误信息,结合具体错误信息进行处理 -3. 收集常见的错误日志,整理相关解决方案(注:欢迎大家补充) - -文档相关: - -- [Docker-Compose官方安装文档](https://docs.docker.com/compose/install/) -- [Docker-ComposeV2官方安装文档](https://docs.docker.com/compose/cli-command/) - -#### 1.4 Docker镜像源下载超时或失败 - -目前TCA基础镜像是使用``python:3.7.12-slim``,该镜像是基于``debian bullseye(debian 11)``版本构建的,对应的源需要选择 ``bullseye`` 版本的源。 - -如果使用默认的下载源会报错或访问速度比较慢,可以调整``server/dockerconfs/Dockerfile-common``,指定其他国内下载源: - -```DockerFile -# FROM python:3.7.12-slim - -# 增加一下内容用于指定下载源 -RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak && \ - echo 'deb http://mirrors.tencent.com/debian/ bullseye main non-free contrib' > /etc/apt/sources.list && \ - echo 'deb http://mirrors.tencent.com/debian/ bullseye-updates main non-free contrib' >> /etc/apt/sources.list && \ - echo 'deb http://mirrors.tencent.com/debian-security bullseye-security main non-free contrib' >> /etc/apt/sources.list - -# ARG EXTRA_TOOLS=... -``` - -如果出现以下错误:``E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages`` -可以做以下检查,确认是什么原因: - -1. 检查一下本地服务器的时间配置是否正常 -2. 调整下载源 - -#### 1.5 Python安装或执行失败 - -使用Python执行时提示``ImportError: libpython3.7m.so.1.0: cannot open shared object file: No such file or directory``,该如何处理 - -1. 在本地安装Python的目录中查找该文件,比如Python的安装目录是``/usr/local/python3``,可以执行``find /usr/local/python3 -name "libpython3.7m.so.1.0"``,确认本地是否存在该文件 -2. 如果本地存在该文件,则执行以下命令:(注:需要将``/usr/local/python3``调整为本地实际的Python3安装路径) - - ```bash - # 链接构建产出的Python动态库 - $ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 - # 配置动态库 - $ ldconfig - ``` - -3. 如果本地不存在该文件,则可能需要重新安装Python3:(注:以下是将Python安装到``/usr/local/python3``,可以根据实际情况进行调整) - - ```bash - # 编译前配置,注意重点:需要加上参数 --enable-shared - $ ./configure prefix=/usr/local/python3 --enable-shared - ``` - -文档相关: - -- [CentOS安装Python3.7文档](https://github.com/Tencent/CodeAnalysis/blob/main/doc/references/install_python37_on_centos.md) -- [Ubuntu安装Python3.7文档](https://github.com/Tencent/CodeAnalysis/blob/main/doc/references/install_python37_on_ubuntu.md) - -#### 1.6 执行``compose_init.sh``脚本的``pip install``提示``sha256``不匹配错误 - -在构建镜像的``pip install``步骤提示以下报错时: - -``` -ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them. - setuptools from https://mirrors.cloud.tencent.com/pypi/packages/fb/58/9efbfe68482dab9557c49d433a60fff9efd7ed8835f829eba8297c2c124a/setuptools-62.1.0-py3-none-any.whl#sha256=26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8: - Expected sha256 26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8 - Got ddaacc49de5c08c09d744573240a9a49f24f65c5c72380e972433784caa68d98 -``` - -可以执行``export ORIGIN=normal``,然后再执行``./compose_init.sh`` ->注:执行``export``命令的作用是调整为``pypi``默认官方下载源进行``pip install`` - -#### 1.7 MacBook M1 使用 Docker-Compose报错 - -在M1机器上使用默认配置启动docker-compose,会出现``mysql``和``scmproxy``服务启动失败,需要做以下两步调整 - -1. 调整``docker-compose.yml``文件,修改MySQL的镜像版本: - - ```bash - # 默认: - image: mysql:5.7.24 - - # 调整后: - image: mariadb:10.5.8 - ``` - -2. 调整``server/dockerconfs/Dockerfile-common``文件,修改Python的镜像版本: - - ```bash - # 默认: - FROM python:3.7.12-slim - - # 调整后: - FROM amd64/python:3.7.12-slim - ``` - -#### 1.8 celery、gunicorn命令找不到 - -如果启动服务时,提示:``celery could not be found``或``gunicorn could not be found``,需要做以下检查 - -1. 执行``python -v``检查输出,确认当前python版本是否为python3.7 -2. 执行``pip install celery``和``pip install gunicorn``检查celery和gunicorn是否已经安装 -3. 如果已经安装,可以执行以下命令建立软链:(注:需要将``/usr/local/python3``调整为本地实际的Python3安装路径) - -```bash -ln -s /usr/local/python3/bin/gunicorn /usr/local/bin/gunicorn -ln -s /usr/local/python3/bin/celery /usr/local/bin/celery -``` - -### 2. 服务启动与初始化 - -#### 2.1 ``compose_init.sh``脚本需要填写的密码是什么? - -执行``compose_init.sh``提示需要输入的密码是数据库的初始化密码,默认为``TCA!@#2021`` - -```bash -$ ./compose_init.sh -Recreating tca_open_source_mysql_1 ... done -Recreating tca_open_source_redis_1 ... done -wait db [DB default password: TCA!@#2021] -Enter password: <此处输入'TCA!@#2021'> -``` - -#### 2.2 服务占用端口异常 - -TCA 本地部署启动后,会监听多个端口: - -- web服务:80 -- nginx服务:8000 -- main服务:8001 -- analysis服务:8002 -- login服务:8003 -- file-nginx服务:8004 -- file服务:8804 -- scmproxy服务:8009 - -如果出现端口占用冲突,建议采用以下方式解决: - -1. 调整其他程序监听的端口号,避免跟上述TCA服务的端口号出现冲突 -2. 采用Docker-Compose方式启动TCA,仅监听80端口 - -不推荐调整TCA指定服务的端口号,需要调整多处配置,以及可能会影响到后续服务的升级 - -#### 2.3 服务输出日志找不到 - -本地部署输出的日志位置: - -1. ``main``服务输出的日志目录:``server/projects/main/log`` - - 服务启动日志:``server/projects/main/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/main/log/gunicorn_access.log`` - - Celery Worker启动日志(处理异步任务):``server/projects/main/nohup_worker.out`` - - Celery Beat启动日志(启动定时任务):``server/projects/main/nohup_beat.out`` - - 服务运行日志:``server/projects/main/log/codedog.log`` - - Celery Worker运行日志:``server/projects/main/log/main_celery.log`` - - Celery Beat运行日志:``server/projects/main/log/main_beat.log`` -2. ``analysis``服务输出的日志目录:``server/projects/analysis/log`` - - 服务启动日志:``server/projects/analysis/log/gunicorn_error.log`` - - Celery Worker启动日志:``server/projects/analysis/nohup.out`` - - 服务接收请求日志:``server/projects/analysis/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/analysis/log/codedog.log`` - - Celery Worker运行日志(处理结果入库):``server/projects/analysis/log/celery.log`` -3. ``login``服务输出的日志目录:``server/projects/login/log`` - - 服务启动日志:``server/projects/login/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/login/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/login/log/codedog.log`` -4. ``file``服务输出的日志目录:``server/projects/file/log`` - - 服务启动日志:``server/projects/file/log/gunicorn_error.log`` - - 服务接收请求日志:``server/projects/file/log/gunicorn_access.log`` - - 服务运行日志:``server/projects/file/log/codedog_file.log`` -5. ``scmproxy``服务输出的日志目录:``server/projects/scmproxy/logs`` - - 服务启动日志:``server/projects/scmproxy/nohup.out`` - - 服务运行日志:``server/projects/scmproxy/logs/scmproxy.log`` - -### 3. 平台使用 - -#### 3.1 平台登录的默认账号密码是什么? - -默认账号: ``CodeDog``,密码: ``admin`` - -#### 3.2 平台默认的API Token是什么? - -默认Token是``0712b895f30c5e958ec71a7c22e1b1a2ad1d5c6b`` - -如果在平台上刷新了``CodeDog``用户的Token,需要将刷新后的Token填写到以下文件中: - -1. ``server/scripts/config.sh``文件 - - 更新``CODEDOG_TOKEN``、``FILE_SERVER_TOKEN``变量的值(3个位置) -2. ``server/dockerconfs/.env.local``文件 - - 更新``CODEDOG_TOKEN``、``FILE_SERVER_TOKEN``变量的值(3个位置) - -然后重启服务。 - -1. 本地部署: - - ```bash - cd server/ - ./scripts/deploy.sh start - ``` - -2. docker-compose部署: - - ```bash - $ docker-compose stop - # 稍等片刻 - $ docker-compose up -d - ``` - -#### 3.3 代码库登记出错,出现代码库及账号不匹配 - -该错误出现可能有以下几个原因: - -1. 账号密码不准确或登记的代码库地址不存在 -2. 登记``github``使用的密码需要使用[``personal access token``](https://github.com/settings/tokens) -3. scmproxy服务启动失败 - - 本地部署:执行``ps aux | grep proxyserver``看看是否有``python proxyserver.py``执行进程,如果不存在可以看一下``server/projects/scmproxy/nohup.out``看看启动失败的原因 - - docker-compose部署:在项目根目录执行``docker-compose ps``看看``scmproxy``容器是否正常启动,如果没有启动,可以执行``docker-compose logs scmproxy``看看启动失败的原因 -4. scmproxy所在的机器/容器因为网络问题无法访问对应的代码库 - - 可以手动在机器/容器中执行``git clone xxxx``(xxx表示待登记的代码库),检查看看是否能够正常拉取 -5. scmproxy所在的机器git版本较低,出现``unknown option `local` ``错误 - - 可以升级机器上的git版本,目前工具支持最低的git版本为``1.8.3.1`` - -#### 3.4 查看问题文件提示**获取代码信息耗时较久,请稍后再试** - -出现该提示的原因是,代码库偏大或``clone``代码库时间较长,可以稍等一会再刷新重试 - -#### 3.5 客户端访问文件服务器,提示``method(upload_file) call fails on error: Expecting value: line 1 column 1 (char 0)`` - -出现这种错误,可能是本地配置异常或token配置有问题,检查方式如下: - -1. 检查客户端的``config.ini``文件配置的URL是否为当前Server部署的地址:(xxx需要调整为实际的路径) - - ```bash - [SERVER_URL] - URL=http://xxx/server/main/ - [FILE_SERVER] - URL=http:/xxx/server/files/ - ``` - - 如果xxx不一致需要调整为一致 - > 注: xxx地址与在浏览器访问平台的xxx地址是一致的,不需要区分端口 -2. 检查客户端访问Server是否能通: - - ```bash - curl -v http://xxx/server/main/ - ``` - - 如果不通,则需要检查客户端机器访问Server机器是否有网络限制 -3. 检查当前在``codedog.ini``-``[config]token``与``config.ini``文件配置的``[FILE_SERVER]TOKEN``是否一致,如果不一致需要调整为一致 -4. 检查用户``CodeDog``的``Token``是否被刷新了然后没有更新到配置文件中 - -#### 3.6 客户端访问文件服务器,提示``Connection timed out`` - -本地客户端执行过程提示``method (upload file) call fails on error: `` 该如何处理? -一般情况下,这个问题是客户端与Server之间网络不通导致,可以检查一下是否有防火墙限制或者配置的URL是内部IP或地址,可以通过以下方式检查 - -1. 检查客户端的``config.ini``文件配置的URL是否为当前Server部署的地址:(xxx需要调整为实际的路径) - - ```bash - [SERVER_URL] - URL=http://xxx/server/main/ - [FILE_SERVER] - URL=http:/xxx/server/files/ - ``` - -2. 检查客户端访问Server是否能通: - - ```bash - curl -v http://xxx/server/main/ - ``` - - 如果不通,则需要检查客户端机器访问Server机器是否有网络限制 - -#### 3.7 任务执行结果异常,提示**第三方依赖文件服务器异常** - -出现该错误提示,一般是访问文件器出错或文件服务器本身有问题,可以通过以下方式检查: -需要检查``analysis-worker``的日志(本地部署:``server/projects/analysis/log/celery.log``,docker-compose部署:``docker-compose exec analysis-worker /bin/bash``进入容器后访问``log/celery.log``查看具体错误原因 - -如果提示``no route to host``可能是当前机器/容器无法访问当前宿主机的IP,可以检查一下当前防火墙的设置,是否限制了``analysis-worker``来源的访问 - -#### 3.8 客户端执行时提示**工具(xxx)扫描进程为空,请联系管理员配置工具进程!** - -出现该错误提示,一般是Server未进行初始化,可以通过执行以下命令初始化后再启动测试 - -- 本地部署:``cd server && ./scripts/deploy.sh init`` -- docker-compose部署:``./compose_init.sh`` - -## CodeAnalysis仓库文件问题 - -### 1. clone到本地时相关md文件内资源图片无法显示 - -为防止国内用户访问CodeAnalysis Github首页时图片资源加载失败,目前各个md文件中的图片资源引用地址调整增加了URL前缀`https://tencent.github.io/CodeAnalysis/`。 - -用户下载代码库到本地后,发现无法访问资源文件时,请检查本地网络是否能够连通外网,如果无法连通外网,可以在文档引入资源地址中进行**相对路径**替换,调整各个资源文件的链接。 - -- 对于根目录下的md文件,直接删除URL前缀即可: - - 例如在`https://tencent.github.io/CodeAnalysis/media/homepage.png`这个链接可以调整为`media/homepage.png` - -- 对于其他目录下的md文件,删除URL前缀后,需调整文件相对路径链接: - - 例如对于`doc/client.md`, 需将`https://tencent.github.io/CodeAnalysis/media/clientConfigIni.png`这个链接调整为`../media/clientConfigIni.png` diff --git a/web/packages/tca-document/zh/quickStarted/codeDeploy.md b/web/packages/tca-document/zh/quickStarted/codeDeploy.md deleted file mode 100644 index 95cd0ae1c..000000000 --- a/web/packages/tca-document/zh/quickStarted/codeDeploy.md +++ /dev/null @@ -1,90 +0,0 @@ -# 源码部署 -兼容旧版的部署方式 -#### 依赖环境 - -- 系统环境 - - Linux - - 最低配置:2核4G内存、100G硬盘存储空间 - -- 环境准备 -> 目前TCA脚本已封装好Python、Mariadb、Redis与Nginx安装步骤,可以按“操作说明”内容进行操作 - - - **Python 3.7**,[安装指引](./references/install_python37_on_centos.md) - - - **MySQL服务(MySQL5.7.8以上版本或Mariadb 10.5以上版本)**,[安装指引](./references/install_mysql_on_centos.md) - - - **Redis服务(4.0版本以上)**,[安装指引](./references/install_redis_on_centos.md) - - - **Nginx服务** - - :::warning - 仅适用于本地部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 - ::: - -- 权限准备 - - - 环境权限:安装 Server 依赖软件(python、nginx、yum 等软件包)需要使用 ROOT 权限 - - 启动 Server服务时可以使用非 ROOT 用户运行 - - 数据库权限:Server 服务执行数据库初始化需要依赖 ``CREATE、ALTER、INDEX、DELETE、LOCK TABLES、SELECT、INSERT、REFERENCES、UPDATE`` 权限 -- 端口使用:需要开放80端口的访问权限(80为TCA平台默认访问端口),或调整 Web 服务默认的访问端口地址 - -#### 操作说明 - -##### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 安装基础软件与部署TCA(可根据脚本选项确定是否要安装相关基础软件),执行 - ```bash - $ bash ./quick_install.sh local deploy - ``` - 执行该命令会做以下事情: - - 检测本地Python3.7、Mariadb/MySQL、Redis与Nginx,如果不存在会提示安装(install) - - 部署TCA Server、Web与Client,并进行初始化(install) - - 启动TCA Server、Web与Client(start) - - 检测TCA的运行状态(check) - - >注:在运行过程中,脚本会检测本地是否安装了相关基础软件(Python3.7、MySQL/Mariadb、Redis、Nignx),如果未安装会输出以下类似提示语: - >``` - >Do you want to install [Redis] by this script? - >Please enter:[Y/N] - >``` - >如果确定通过脚本安装可以输入`Y`。 -3. 执行完成,无其他报错,即可登录: - - TCA 平台初始登录账号是``CodeDog``,密码是``admin``, - -##### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `bash ./quick_install.sh local install tca`:更新相关配置 - - `bash ./quick_install.sh local start`:启动服务(会自动关闭之前的服务) - - `bash ./quick_install.sh local check`:检查服务是否启动失败 - -注: -1. `local install`命令行参数说明: - - `base`:安装Python、Mariadb/MySQL、Redis与Nginx - - `tca`:初始化或更新TCA Server、Web、Client相关配置和数据 - - `server`:初始化或更新TCA Server相关配置和数据 - - `web`:初始化或更新TCA Web相关配置和数据 - - `client`:初始化或更新TCA Client相关配置和数据 - - 不填参数,默认会执行`base`、`tca`相关操作 - -##### 启动和停止服务 - -- 启动所有服务:`bash ./quick_install.sh local start` -- 启动Main相关服务:`bash ./quick_install.sh local start main` - - `local start`支持启动指定服务,如上述的启动Main服务,还支持`mysql/redis/analysis/file/login/scmproxy/nginx/client/all` -- 停止所有服务:`.bash /quick_install.sh local stop` -- 停止Main相关服务:`bash ./quick_install.sh local stop main` - - `local stop`支持停止指定服务,如上述的停止Main服务,还支持`analysis/file/login/scmproxy/nginx/client/all` - -注: -1. 启动时会自动关闭之前已经运行的服务 -2. `local start`支持启动指定服务,如上述的启动Main服务,还支持`mysql/redis/main/analysis/file/login/scmproxy/nginx/all` - - `mysql`和`redis`默认会使用`systemctl`进行启动,如果`systemctl`无法使用,则会直接使用`nohup`方式运行相关服务 - -##### 检查服务运行状态 -检查服务运行状态:`bash ./quick_install.sh local check` - - 目前支持检查server与web,暂不支持client - -##### 获取服务输出日志 -打印TCA Server各个服务的日志路径: `bash ./quick_install.sh local log` \ No newline at end of file diff --git a/web/packages/tca-document/zh/quickStarted/deployClient.md b/web/packages/tca-document/zh/quickStarted/deployClient.md deleted file mode 100644 index 723dd738e..000000000 --- a/web/packages/tca-document/zh/quickStarted/deployClient.md +++ /dev/null @@ -1,182 +0,0 @@ -# 部署与配置客户端 - -## 通过源代码 - -### 依赖环境 - -- 系统环境 - - - Linux,Windows或macOS - -- 环境准备 - - - **Python 3.7**,[安装指引](./references/install_python37_on_centos.md) - -### 使用步骤 - -#### 安装第三方库 - -```bash -# 源码根目录下执行 -pip3 install -r client/requirements/app_reqs.pip -``` - -#### 安装第三方工具 - -```bash -# 源码根目录 -cd client/requirements - -# 执行安装脚本 -# Linux/macOS环境 -./install.sh -# Windows环境 -./install.bat -``` - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - - 将 `` 替换成实际的serve ip(可包含端口号)。 - - ![客户端执行环境配置](https://tencent.github.io/CodeAnalysis/media/clientConfigIni.png) - -- 配置 `client/codedog.ini` 文件 - - 必填项:`token`、`org_sid`、`team_name`、`source_dir` - - - **个人令牌** - `token`:从 TCA 页面获取,前往[个人中心]-[个人令牌]-复制Token - - ![personalToken](../../images/personalToken.png) - - - **团队编号** - `org_sid`:进入 TCA 项目概览页,从 URL 中获取 - - - **项目名称** - `team_name`::进入 TCA 项目概览页,从 URL 中获取 - - :::tip - 项目概览URL格式:`http://{域名}/t/{org_sid}/p/{team_name}/profile` - ::: - - - **分析路径** - `source_dir`: 本地代码目录路径 - - :::tip - - 如果项目代码为编译型语言(比如:C/C++,C#,Go,Java,Kotlin,Objective-C等),且使用的分析方案中配置了编译型工具(如图,使用了OC推荐规则包),需要填写`build_cmd`编译命令。 - - - 其他可选项按需填写,不填写时按默认配置执行 - ::: - -#### 启动客户端 - -```bash -# 源码根目录 -cd client - -# 执行客户端脚本 -python3 codepuppy.py localscan -``` - -:::warning -Client 的实现及启动脚本均依赖 Python3 版本为 3.7,可执行 ``python3 --version`` 查看版本。若版本有误,可安装版本为3.7的python并软链接到python3命令。 -::: - -:::tip - -- `codedog.ini` 各项参数可由命令行传入,获取详细参数说明可运行 `python3 codepuppy.py localscan -h` - -- 使用`localscan`命令启动本地单次的代码分析,如需启动分布式并行分析任务,请参考[使用分布式节点模式](../client/README.md#五使用分布式节点模式执行客户端)进行配置。 -::: - -## 通过Docker-Compose - -:::tip -适用于快速上手体验。使用docker运行,可以免去客户端环境依赖的安装,避免环境兼容性问题。 - -但是由于环境受限于docker,会无法复用本地的编译环境,部分需要编译的工具无法使用。 -::: - -### 使用步骤 - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - -- 配置 `client/codedog.ini` 文件 - -:::tip -同通过源代码使用-[配置客户端](./deployClient.md#配置客户端) -::: - -#### 构建镜像 - -1. 安装Docker,安装教程:[官方文档](https://docs.docker.com/engine/install/) - -2. 安装Docker-Compose,安装教程:[官方文档](https://docs.docker.com/compose/install/) - -3. 进入`client`目录,构建docker镜像 - -```bash -docker build -t tca-client . -``` - -#### 启动客户端 - -##### 方案一:直接使用docker运行 - -进入`client`目录,执行以下命令 - -```bash -# 按照实际情况填写`SOURCE_DIR`环境变量值 -export SOURCE_DIR=需要扫描的代码目录绝对路径 -docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client -``` - -##### 方案二:使用docker内bash终端运行 - -1. 进入docker容器内的bash终端 - - ```bash - # 按照实际情况填写`SOURCE_DIR`环境变量值 - export SOURCE_DIR=需要扫描的代码目录绝对路径 - docker run -it --rm -v $PWD:/workspace/client -v $SOURCE_DIR:/workspace/src --name tca-client tca-client bash - ``` - -2. 通过命令行启动client代码 - - ```bash - python3 codepuppy.py localscan - ``` - -## 通过可执行文件 - -### 依赖环境 - -- 系统环境 - - - Linux,Windows或macOS - -### 使用步骤 - -#### 下载客户端 - -1. 从[发布页面](https://github.com/Tencent/CodeAnalysis/releases)下载与系统相对应的客户端压缩包到本地。 - -2. 解压缩。 - -#### 配置客户端 - -- 配置 `client/config.ini` 文件 - -- 配置 `client/codedog.ini` 文件 - -:::tip -同通过源代码使用-[配置客户端](./deployClient.md#配置客户端) -::: - -#### 启动客户端 - -进入到`client`目录下,执行客户端 - -```bash -./codepuppy localscan -``` diff --git a/web/packages/tca-document/zh/quickStarted/deploySever.md b/web/packages/tca-document/zh/quickStarted/deploySever.md deleted file mode 100644 index 7ee1a6e54..000000000 --- a/web/packages/tca-document/zh/quickStarted/deploySever.md +++ /dev/null @@ -1,130 +0,0 @@ -# 部署 TCA -TCA提供部署脚本,支持一键式快速部署Server、Web、Client。 -脚本共提供三种部署方式:Docker部署(推荐)、[Docker-Compose部署](./dockercomposeDeploy.md)、[源码部署](./codeDeploy.md),可根据您的具体使用场景任意选择其一进行部署。 - -## Docker快速部署 - -:::warning -仅适用于Docker部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 -::: - -### 依赖环境 - -- 系统环境 - - Linux、macOS、Windows - - 最低配置:2核4G内存、100G硬盘存储空间 -- 环境准备 - - Docker -- 权限准备 - - 需要开放80、8000端口的访问权限(80为TCA平台访问端口,8000为TCA Server访问端口) - -### 部署对象 -Server、Web 与 Client - -### 操作说明 -#### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 执行命令: - ```bash - bash ./quick_install.sh docker deploy - ``` -::: tip -通过Docker部署默认会在当前根目录下的挂载三个路径: -- `.docker_temp/logs`:容器内的`/var/log/tca/`,存放TCA平台的日输出文件; -- `.docker_temp/data`:容器内的`/var/opt/tca/`, 存放TCA平台的服务数据,主要是Mariadb、Redis; -- `.docker_temp/configs`:容器内的``/etc/tca``,存放TCA平台的配置文件,主要是`config.sh` -::: - -#### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `TCA_IMAGE_BUILD=true ./quick_install.sh docker deploy`:重新构建并启动tca容器 -::: tip -`TCA_IMAGE_BUILD=true`表示从本地构建TCA镜像运行 -::: - -#### 运行容器 -如果已经在机器上执行过``docker deploy``,并保留容器数据的,可以执行以下命令启动容器,继续运行TCA - -```bash -bash ./quick_install.sh docker start -``` - -#### 停止容器 -如果容器正在运行,希望停止容器,可以运行 - -```bash -bash ./quick_install.sh docker stop -``` - -# 使用TCA -成功部署TCA后,请开始您的代码分析。 -## 进入平台页面 - -在浏览器输入`http://部署机器IP/`,点击立即体验,完成登录后即可跳转到团队列表页 - -:::tip -默认平台登录账号/密码:CodeDog/admin - -如部署过程中,已调整默认账号密码,请按照调整后的账号密码进行登录 -::: - -## 创建团队及项目 - -- 完成团队创建 - -- 完成项目创建 - -## 登记代码库 - -登记代码库,输入代码库地址以及凭证信息等,完成代码库登记。 - -![registerCodeRepo](../../images/registerCodeRepo.png) - -## 创建分析项目 - -![开始分析](../../images/start_scan_02.png) - -::: tip -1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 -2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目。 -::: - -### 分析方案说明 - -- 分析方案是用于对代码库进行分析的一套配置集合。 - -- 更多分析方案配置可查阅[帮助文档-分析方案](../guide/分析方案/基础属性配置.md) - -![creataAnalysePlan](../../images/creataAnalysePlan.png) - -::: tip -本次部署会默认启动运行环境为「Codedog_Linux」的客户端,若需扩展更多运行环境,详见客户端[常驻节点分析](../guide/客户端/常驻节点分析.md) -::: - -![planPage](../../images/planPage.png) - -## 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../images/start_scan_06.png) - -::: tip -- TCA推荐使用`在线分析`,您可根据具体使用场景选择其一。 -- `在线分析`表示配置代码库链接后,TCA客户端拉取代码后进行分析;`客户端分析`在配置本地待扫描代码路径后,无需代码拉取直接分析本地代码。 -- `在线分析`与`客户端分析`具体详情及配置参考[TCA客户端配置详情](../guide/客户端/配置详情.md) -::: - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../guide/代码检查/分析结果查看.md) 等。 - -![分支概览](../../images/start_scan_04.png) \ No newline at end of file diff --git a/web/packages/tca-document/zh/quickStarted/dockercomposeDeploy.md b/web/packages/tca-document/zh/quickStarted/dockercomposeDeploy.md deleted file mode 100644 index e9062bb65..000000000 --- a/web/packages/tca-document/zh/quickStarted/dockercomposeDeploy.md +++ /dev/null @@ -1,49 +0,0 @@ -# Docker-Compose快速部署 -#### 部署对象 -Server、Web 与 Client - -:::warning -仅适用于Docker-Compose部署体验,生产环境建议使用专业的 MySQL、Redis 等服务 -兼容之前的部署方式 -::: - -#### 操作说明 -##### 首次启动操作 - -1. 进入CodeAnalysis工作目录(例如``~/CodeAnalysis``),以下路径均为目录内的相对路径 -2. 执行命令: - - `bash ./quick_install.sh docker-compose deploy`:启动tca_server容器 - -注意:通过Docker-Compose部署默认会在当前根目录下的挂载三个路径: - -- `.docker_data/logs`:存放TCA平台的各个服务日志输出目录; -- `.docker_data/mysql`:存放TCA平台的MySQL数据 -- `.docker_data/redis`:存放TCA平台的Redis数据 -- `.docker_data/filedata`:存放TCA平台文件服务器的文件 - -##### 更新操作 -1. 更新代码 -2. 执行以下命令: - - `bash ./quick_install.sh docker-compose build`:重新构建TCA相关镜像 - - `bash ./quick_install.sh docker-compose deploy`: 重新部署TCA相关容器与初始化(或刷新数据) - -##### 运行操作 -如果已经在机器上执行过``docker-compose deploy``,并保留容器数据的,可以执行以下命令启动容器,继续运行TCA - -```bash -bash ./quick_install.sh docker-compose start -``` - -##### 停止操作 -如果容器正在运行,希望停止容器,可以执行以下命令 - -```bash -bash ./quick_install.sh docker-compose stop -``` - -##### 构建镜像操作 -如果希望构建镜像,可以执行以下命令 - -``` -bash ./quick_install.sh docker-compose build -``` \ No newline at end of file diff --git a/web/packages/tca-document/zh/quickStarted/initRepo.md b/web/packages/tca-document/zh/quickStarted/initRepo.md deleted file mode 100644 index f96467f0f..000000000 --- a/web/packages/tca-document/zh/quickStarted/initRepo.md +++ /dev/null @@ -1,45 +0,0 @@ -# 创建代码分析项目 - -成功部署并启动 Server 与 Web 服务后,通过以下步骤创建您的第一个代码分析项目。 - -## 进入平台页面 - -在浏览器输入`http://部署机器IP/`,点击立即体验,完成登录后即可跳转到团队列表页 - -:::tip -默认平台登录账号/密码:CodeDog/admin - -如部署过程中,已调整默认账号密码,请按照调整后的账号密码进行登录 -::: - -## 创建团队及项目 - -- 完成团队创建 - -- 完成项目创建 - -## 登记代码库 - -登记代码库,输入代码库地址以及凭证信息等,完成代码库登记。 - -![registerCodeRepo](../../images/registerCodeRepo.png) - -## 创建分析项目 - -![开始分析](../../images/start_scan_02.png) - -::: tip - -1. 用户可选择使用分析方案模板,或创建分析方案的方式,利用方案的分析配置进行代码分析。 -2. 点击确认时,平台会首先创建该代码库的分析方案,然后根据代码库分支、当前分析方案创建分支项目。 -::: - -### 分析方案说明 - -- 分析方案是用于对代码库进行分析的一套配置集合。 - -- 更多分析方案配置可查阅[帮助文档-分析方案](../guide/分析方案/基础属性配置.md) - -![creataAnalysePlan](../../images/creataAnalysePlan.png) - -![planPage](../../images/planPage.png) diff --git a/web/packages/tca-document/zh/quickStarted/intro.md b/web/packages/tca-document/zh/quickStarted/intro.md deleted file mode 100644 index 055ce7737..000000000 --- a/web/packages/tca-document/zh/quickStarted/intro.md +++ /dev/null @@ -1,36 +0,0 @@ -# 平台概述 - -**腾讯云代码分析**(Tencent Cloud Code Analysis,简称TCA,内部曾用研发代号 **CodeDog** )是集众多分析工具的云原生、分布式、高性能的代码综合分析跟踪平台,包含服务端、Web端和客户端三个组件,已集成一批自研工具,同时也支持动态集成业界各编程语言的分析工具。 - -### 使用TCA Action快速体验 -使用TCA Action,只需要在代码仓库中添加`.github/workflows/tca.yml`文件,就可以直接在GitHub工作流中快速体验代码分析。请参考:[TCA-action指引](https://github.com/TCATools/TCA-action/blob/main/README.md) - -### 部署TCA - -拉取 [代码库](https://github.com/Tencent/CodeAnalysis) 后,您可以通过以下三种方式部署腾讯云代码分析平台: - -- [通过 Docker 部署](./deploySever.md#通过docker) - -- [通过源代码](./codeDeploy.md#通过源代码) - -- [通过 Docker-Compose 部署](./dockercomposeDeploy.md#通过docker-compose) - -### 创建首个代码分析项目 - -成功部署并启动TCA后,您可以按照 [指引](./deploySever.md) 创建您的首个代码分析项目。 - -:::tip -默认平台登录账号/密码:CodeDog/admin -::: - -### 快速扩展客户端 - -TCA客户端支持通过可执行文件进行快速扩展部署,详见[通过可执行文件](./deployClient.md#通过可执行文件) - -:::tip -客户端可在本地执行代码分析,也可以作为[在线常驻节点](../advanced/任务分布式执行.md)进行在线分析。 -::: - -### 了解更多 - -更多关于腾讯云代码分析平台的使用指南和配置说明,参见[帮助文档](../guide/README.md)。 diff --git a/web/packages/tca-document/zh/quickStarted/references/install_mysql_on_centos.md b/web/packages/tca-document/zh/quickStarted/references/install_mysql_on_centos.md deleted file mode 100644 index 0337b5cfc..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_mysql_on_centos.md +++ /dev/null @@ -1,102 +0,0 @@ -# 在 CentOS 安装 MySQL - -## 注意 - -本文档仅供参考,不适用于正式环境部署,正式环境建议使用专业的MySQL服务(比如[腾讯云的MySQL产品](https://cloud.tencent.com/product/cdb)) - -## 环境 - -CentOS 7.3 版本 - -## 安装 mysql yum源 - -```bash -wget https://repo.mysql.com//mysql57-community-release-el7-11.noarch.rpm -yum localinstall mysql57-community-release-el7-11.noarch.rpm -``` - -安装成功后,查看MySQL版本: - -```bash -yum repolist all | grep mysql -``` - -输出结果: - -```bash -mysql-cluster-7.5-community/x86_64 MySQL Cluster 7.5 Community 禁用 -mysql-cluster-7.5-community-source MySQL Cluster 7.5 Community - 禁用 -mysql-cluster-7.6-community/x86_64 MySQL Cluster 7.6 Community 禁用 -mysql-cluster-7.6-community-source MySQL Cluster 7.6 Community - 禁用 -!mysql-connectors-community/x86_64 MySQL Connectors Community 启用: 221 -mysql-connectors-community-source MySQL Connectors Community - S 禁用 -!mysql-tools-community/x86_64 MySQL Tools Community 启用: 135 -mysql-tools-community-source MySQL Tools Community - Source 禁用 -mysql-tools-preview/x86_64 MySQL Tools Preview 禁用 -mysql-tools-preview-source MySQL Tools Preview - Source 禁用 -mysql55-community/x86_64 MySQL 5.5 Community Server 禁用 -mysql55-community-source MySQL 5.5 Community Server - S 禁用 -mysql56-community/x86_64 MySQL 5.6 Community Server 禁用 -mysql56-community-source MySQL 5.6 Community Server - S 禁用 -!mysql57-community/x86_64 MySQL 5.7 Community Server 启用: 544 -mysql57-community-source MySQL 5.7 Community Server - S 禁用 -mysql80-community/x86_64 MySQL 8.0 Community Server 禁用 -mysql80-community-source MySQL 8.0 Community Server - S 禁用 -``` - -## 安装MySQL - -```bash -yum install mysql-community-server -``` - ->1.如遇以下报错,可尝试运行`yum install mysql-community-server --nogpgcheck`安装 -> Public key for mysql-community-libs-compat-5.7.37-1.el7.x86_64.rpm is not installed -> Failing package is: mysql-community-libs-compat-5.7.37-1.el7.x86_64 -> GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql ->2.如遇以下报错,可执行`yum module disable mysql`后重试安装 ->All matches were filtered out by modular filtering for argument: mysql-community-serve ->Error: Unable to find a match: mysql-community-server - -## 配置MySQL服务 - -安装好的MySQL配置文件路径是``/etc/my.cnf``,这里可以根据需要调整,比如可以调整: - -- datadir:MySQL存放数据的路径,如果有额外挂载磁盘,可以考虑指向相关路径 - -## 启动MySQL服务 - -```bash -systemctl start mysqld -``` - -确认MySQL正常启动 - -```bash -systemctl status mysqld -``` - -查看生成 MySQL root用户临时密码: - -```bash -grep 'temporary password' /var/log/mysqld.log -``` - -### 修改root用户密码 - -连接MySQL服务 - -```bash -$ mysql -uroot -p -# 输出上述查询到的临时密码 -``` - -修改root用户的密码(下面是改成 ``Password@2021``,这里根据自行需要进行调整): - -```SQL -ALTER USER 'root'@'localhost' IDENTIFIED BY 'Password@2021'; -``` - -## 参考文档 - -- [Installing MySQL on Linux Using the MySQL Yum Repository](https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html) diff --git a/web/packages/tca-document/zh/quickStarted/references/install_nginx_from_source.md b/web/packages/tca-document/zh/quickStarted/references/install_nginx_from_source.md deleted file mode 100644 index ca924bf4a..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_nginx_from_source.md +++ /dev/null @@ -1,136 +0,0 @@ -# 源码安装 Nginx - -## 运行环境 - -1. 基于x86_64的CentOS -2. 基于aarch64(鲲鹏920)的UOS V20 -3. 基于aarch64(飞腾2000)的TencentOS Server - -## 环境准备 - -安装编译打包需要的工具 - -```bash -yum -y install gcc zlib-devel pcre-devel bzip2-devel openssl-devel readline-devel -``` -> Ubuntu: ``apt install gcc libssl-dev zlib1g-dev libpcre3-dev libbz2-dev libreadline-dev`` - -## 下载源码 - -```bash -wget http://nginx.org/download/nginx-1.20.2.tar.gz -``` - -## 解压安装 - -```bash -# 解压 -$ tar zvxf nginx-1.20.2.tar.gz -C /usr/local/src - -# 进入源码目录 -$ cd /usr/local/src/nginx-1.20.2 - -# 配置 -$ ./configure \ ---sbin-path=/usr/local/nginx/nginx \ ---conf-path=/etc/nginx/nginx.conf \ ---pid-path=/run/nginx.pid \ ---with-stream \ ---with-http_ssl_module --with-http_v2_module --with-http_auth_request_module - -# 构建nginx -$ make -j4 -$ make install -$ make clean - -# 建立软链 -$ ln -s /usr/local/nginx/nginx /usr/local/bin/nginx -``` - -## 添加nginx配置文件 - -```bash -mkdir /etc/nginx/conf.d/ -vi /etc/nginx/nginx.conf -``` - -检查``nginx.conf``配置文件: - -1. 检查``pid /run/nginx.pid``,如果缺失或被注释则加上,加上位置如下所示: -2. 检查是否缺失这一行``include conf.d/*.conf;``,如果缺失则加上,加上位置如下所示: - -```bash -# ...省略内容 -#pid logs/nginx.pid; # 默认有的 -pid /run/nginx.pid; - -events { - # ...省略内容 -} - -# ...省略内容 - -http { - # ...省略内容 - # - include conf.d/*.conf; - server { - # ...省略内容 - } -} - -``` - -后续可以将nginx配置文件放置到``/etc/nginx/conf.d/``目录下 - - - -## 配置开机自动启动 - -```bash -vim /usr/lib/systemd/system/nginx.service -``` - -输入以下内容: - -```bash -[Unit] -Description=The nginx HTTP and reverse proxy server -After=network-online.target remote-fs.target nss-lookup.target -Wants=network-online.target - -[Service] -Type=forking -PIDFile=/run/nginx.pid -# Nginx will fail to start if /run/nginx.pid already exists but has the wrong -# SELinux context. This might happen when running `nginx -t` from the cmdline. -# https://bugzilla.redhat.com/show_bug.cgi?id=1268621 -ExecStartPre=/bin/rm -f /run/nginx.pid -ExecStartPre=/usr/local/bin/nginx -t -ExecStart=/usr/local/bin/nginx -ExecReload=/usr/local/bin/nginx -s reload -ExecStop=/usr/local/bin/nginx -s stop -KillSignal=SIGQUIT -TimeoutStopSec=5 -KillMode=process -PrivateTmp=true - -[Install] -WantedBy=multi-user.target -``` - -启动nginx: - -```bash -systemctl start nginx -``` - -开机自动启动nginx: - -```bash -systemctl enable nginx -``` - -## 参考文档 - -- [Nginx官方文档](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#downloading-the-sources) diff --git a/web/packages/tca-document/zh/quickStarted/references/install_python37_on_centos.md b/web/packages/tca-document/zh/quickStarted/references/install_python37_on_centos.md deleted file mode 100644 index ac782a828..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_python37_on_centos.md +++ /dev/null @@ -1,109 +0,0 @@ -# 在 CentOS 安装 Python3.7 - -## 下载Python源码包 - -```bash -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz -``` - -## 安装前准备 - -安装依赖组件 - -```bash -yum -y install wget zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel xz-devel -``` - -## 解压安装 - -```bash -# 解压到/usr/local/src目录 -$ tar zvxf Python-3.7.12.tgz -C /usr/local/src -$ cd /usr/local/src/Python-3.7.12 -# 编译前配置 -$ ./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -$ make -j8 -# 安装Python -$ make install -# 清理编译产出的中间文件 -$ make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -$ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -$ ldconfig -``` - -## 检查 - -检查Python版本是否安装成功 - -```bash -$ python --version -Python 3.7.12 # 正常输出,表示安装成功 -``` - -注: - -1. 链接到/usr/local/bin/目录不会影响系统软件(比如yum)的使用,因为 yum 工具指定的Python路径是``/usr/bin/python`` -2. 一般情况下,PATH配置是先``/usr/local/bin``再``/usr/bin`` -3. 检查``python -v``输出结果是否为``Python 3.7.12``版本,如果不是该版本,可能影响后续依赖安装和服务运行 - -## pypi下载源配置 - -pip默认是到``pypi``官方源下载第三方依赖包,下载速度可能会比较慢,可以考虑调整为腾讯云的``pypi``下载源,调整方式: - -```bash -mkdir ~/.pip/ -echo "extra-index-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` - -## 一键安装脚本 -以下脚本内容是上面的步骤集合,省去了复制粘贴的重复动作。 -1. 创建文件 `install_py37.sh`,写入以下 shell 脚本 -2. 赋予执行权限,`chmox +x install_py37.sh` -3. 执行脚本,`./install_py37.sh` - -```bash -#!/bin/env bash - -## 下载 Python 源码,如果已下载源码在脚本当前目录下,可注释跳过下载步骤 -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz - -## 安装编译依赖组件 -yum -y install wget zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel xz-devel - -## 解压安装 -# 解压到/usr/local/src目录 -tar zvxf Python-3.7.12.tgz -C /usr/local/src -cd /usr/local/src/Python-3.7.12 -# 编译前配置 -./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -make -j8 -# 安装Python -make install -# 清理编译产出的中间文件 -make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -ldconfig - -## 检查Python版本是否安装成功 -echo -e "\033[1;42;37m[$(date "+%Y/%m/%d %H:%M:%S")] [Check]: 检查Python版本\033[0m" -python --version -echo -e "\033[1;42;37m[$(date "+%Y/%m/%d %H:%M:%S")] [Check]: 检查Python版本\033[0m" - -## pypi下载源配置 -mkdir ~/.pip/ -echo "extra-index-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` diff --git a/web/packages/tca-document/zh/quickStarted/references/install_python37_on_ubuntu.md b/web/packages/tca-document/zh/quickStarted/references/install_python37_on_ubuntu.md deleted file mode 100644 index 14459aaf1..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_python37_on_ubuntu.md +++ /dev/null @@ -1,66 +0,0 @@ -# 在 Ubuntu 安装 Python3.7 - -> 注:当前Ubuntu版本为18.04 - -## 下载Python源码包 - -```bash -wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz -``` - -## 安装前准备 - -安装依赖组件 - -```bash -apt-get update -apt-get install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libsqlite3-dev libreadline-dev libffi-dev wget libbz2-dev tk-dev gcc make -``` - -## 解压安装 - -```bash -# 解压到/usr/local/src目录 -$ tar zvxf Python-3.7.12.tgz -C /usr/local/src -$ cd /usr/local/src/Python-3.7.12 -# 编译前配置 -$ ./configure prefix=/usr/local/python3 --enable-shared -# 编译构建 -$ make -j8 -# 安装Python -$ make install -# 清理编译产出的中间文件 -$ make clean -# 链接构建产出的Python可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/python3 /usr/local/bin/python -# 链接构建产出的pip3可执行文件到/usr/local/bin目录 -$ ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip -# 链接构建产出的Python动态库 -$ ln -s /usr/local/python3/lib/libpython3.7m.so.1.0 /usr/lib/libpython3.7m.so.1.0 -# 配置动态库 -$ ldconfig -``` - -## 检查 - -检查Python版本是否安装成功 - -```bash -$ python --version -Python 3.7.12 # 正常输出,表示安装成功 -``` - -注: - -1. 链接到/usr/local/bin/目录不会影响系统软件 -2. 一般情况下,PATH配置是先``/usr/local/bin``再``/usr/bin`` -3. 检查``python -v``输出结果是否为``Python 3.7.12``版本,如果不是该版本,可能影响后续依赖安装和服务运行 - -## pypi下载源配置 - -pip默认是到``pypi``官方源下载第三方依赖包,下载速度可能会比较慢,可以考虑调整为腾讯云的``pypi``下载源,调整方式: - -```bash -mkdir ~/.pip/ -echo "[global]\nindex-url = https://mirrors.cloud.tencent.com/pypi/simple" >> ~/.pip/pip.conf -``` diff --git a/web/packages/tca-document/zh/quickStarted/references/install_redis_from_source.md b/web/packages/tca-document/zh/quickStarted/references/install_redis_from_source.md deleted file mode 100644 index 3ad90db98..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_redis_from_source.md +++ /dev/null @@ -1,107 +0,0 @@ -# 源码安装 Redis - -## 运行环境 - -1. 基于x86_64的CentOS -2. 基于鲲鹏920(aarch64)的UOS V20 -3. 基于飞腾2000(aarch64)的TencentOS Server - -## 环境准备 - -安装编译打包需要的工具 - -```bash -yum install -y gcc make tcl wget -``` - -## 下载源码 - -```bash -wget http://download.redis.io/releases/redis-5.0.4.tar.gz -``` - -## 编译安装 - -```bash -# 解压 -$ tar zvxf redis-5.0.4.tar.gz -C /usr/local/src - -# 进入源码目录 -$ cd /usr/local/src/redis-5.0.4 - -# 构建redis依赖库 -$ cd deps; make -j4 hiredis jemalloc linenoise lua -$ cd .. - -# 构建redis -$ make -j4 -$ make install -$ make clean -``` - -安装后,可以在``/usr/local/src/redis-5.0.4/src``目录和``/usr/local/bin/``目录下找到``redis-server``与``redis-cli``两个文件 - -## 调整配置 - -```bash -cp /usr/local/src/redis/redis.conf /etc/redis.conf -vim /usr/local/src/redis/redis.conf -``` - -```bash -# 设置Redis密码 -requirepass 123456 - -# 将 daemonize no 调整为 daemonize yes,将redis-server调整为默认后台启动 -daemonize yes - -# 配置日志 -logfile '/var/log/redis/redis-server.log' -``` - -## 启动服务 - -```bash -redis-server /etc/redis.conf -``` - -## 配置开机自动启动 - -```bash -vim /etc/systemd/system/redis.service -``` - -输入以下内容: - -```service -[Unit] -Description=redis-server -After=network.target - -[Service] -Type=forking -ExecStart=/usr/local/bin/redis-server /etc/redis.conf -ExecStop=/usr/local/bin/redis-cli shutdown -Restart=always - -PrivateTmp=true - -[Install] -WantedBy=multi-user.target -``` - -启动redis-server: - -```bash -systemctl start redis -``` - -开机自动启动redis: - -```bash -systemctl enable redis -``` - -## 参考文档 - -- [Redis官方文档](https://redis.io/topics/quickstart) diff --git a/web/packages/tca-document/zh/quickStarted/references/install_redis_on_centos.md b/web/packages/tca-document/zh/quickStarted/references/install_redis_on_centos.md deleted file mode 100644 index 1a10cf9be..000000000 --- a/web/packages/tca-document/zh/quickStarted/references/install_redis_on_centos.md +++ /dev/null @@ -1,48 +0,0 @@ -# 在 CentOS 安装 Redis - -## 注意 - -本文档仅供参考,不适用于正式环境部署,正式环境建议使用专业的Redis服务(比如[腾讯云的Redis产品](https://cloud.tencent.com/product/crs)) - -## 环境 - -CentOS 7.3 版本 - -## yum 安装 redis - -```bash -yum install redis -``` - -注:安装redis可能会出现"no package redis available"的错误提示,请执行``yum install epel-release``后重试redis安装命令。 - -## 修改redis密码 - -```bash -$ vi /etc/redis.conf - -# 找到 requirepass foobared -# 复制一行并根据自己需要调整密码,比如 -requirepass tca123 -``` - -## 启动redis - -```bash -systemctl start redis -``` - -查看redis运行状态 - -```bash -systemctl status redis -``` - -## 访问redis - -```bash -$ redis-cli - -127.0.0.1:6379> auth tca123 -OK # 鉴权通过 -``` diff --git a/web/packages/tca-document/zh/quickStarted/runProject.md b/web/packages/tca-document/zh/quickStarted/runProject.md deleted file mode 100644 index 3fa362da5..000000000 --- a/web/packages/tca-document/zh/quickStarted/runProject.md +++ /dev/null @@ -1,26 +0,0 @@ -# 启动代码分析 - -在完成 Server、Web 和 Client 相关部署和配置后,可通过平台执行代码分析。 - -## 执行代码分析 - -初始化创建项目后,可通过 `在线分析` 或 `客户端分析` 来启动代码分析。 - -![代码分析](../../images/start_scan_06.png) - -注: -- TCA推荐使用`在线分析`,您可根据具体使用场景选择其一。 -- `在线分析`表示配置代码库链接后,TCA客户端拉取代码后进行分析;`客户端分析`在配置本地待扫描代码路径后,无需代码拉取直接分析本地代码。 -- `在线分析`与`客户端分析`具体详情及配置参考[TCA客户端配置详情](../guide/客户端/客户端配置详情.md) - -## 查看分析历史 - -分析结束后,数据会上报到服务端。可进入分析历史页面查看分析记录以及分析结果。 - -![分析历史](../../images/start_scan_05.png) - -## 查看分析概览 - -分析结束后,进入分支概览可以查看该分支指定分析方案的概览数据以及 [问题列表](../guide/代码检查/分析结果查看.md) 等。 - -![分支概览](../../images/start_scan_04.png) diff --git a/web/packages/tca-document/zh/quickStarted/tools.md b/web/packages/tca-document/zh/quickStarted/tools.md deleted file mode 100644 index a4c47ba0f..000000000 --- a/web/packages/tca-document/zh/quickStarted/tools.md +++ /dev/null @@ -1,47 +0,0 @@ -# 工具列表 - -目前 TCA 支持以下工具: - -| 官方工具 | 第三方工具 | -| :--------: | :-------: | -|[0daychecker](https://github.com/Tencent/CodeAnalysis/tree/main/tools/codedog_0Day_checker)| androidlint | -|clangwarning| checkstyle | -|codecount| clang | -|customfilescan| cobra | -|customscan| cpd | -|fbrjs| cppcheck | -|javawarning| cpplint | -|regexfilescan| dart_code_metrics | -|regexscan| dartanalyzer | -|[tca_ql_php_beta](https://github.com/Tencent/CodeAnalysis/tree/main/tools/Hades_Beta)| detekt | -|unusedresource| eslint | -|[collie](https://github.com/Tencent/CodeAnalysis/tree/main/tools/collie/)| eslint_typescript | -|[compass](https://github.com/Tencent/CodeAnalysis/tree/main/tools/compass)| eslint_vue | -|| findbugs | -|| flake8 | -|| [flawfinder](https://github.com/TCATools/flawfinder) | -|| flow | -|| golangcilint | -|| gometalinter | -|| htmlcs | -|| infer_cpp | -|| infer_java | -|| infer_objectivec | -|| [ktlint](https://github.com/TCATools/custom-ktlint) | -|| [kunlun-M](https://github.com/TCATools/common-kunlun.git) | -|| lizard | -|| luacheck | -|| [phpcs](https://github.com/TCATools/custom-phpcs) | -|| pmd | -|| pylint | -|| [rips](https://github.com/TCATools/rips-scanner) | -|| scalastyle | -|| [semgrep](https://github.com/TCATools/custom-semgrep) | -|| [shellcheck](https://github.com/TCATools/shellcheck) | -|| [spotbugs](https://github.com/TCATools/spotbugs) | -|| stylecop | -|| stylelint | -|| swiftlint | -|| [sonarqube](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq.py) | -|| [sonarqube_java](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq_java.py) | -|| [sonarqube_cs](https://github.com/GabrielLegend/tca_plugin_sonarqube/blob/main/src/sq_cs.py) | diff --git a/web/packages/tca-layout/global.d.ts b/web/packages/tca-layout/global.d.ts index 9f979b9c9..585ed1325 100644 --- a/web/packages/tca-layout/global.d.ts +++ b/web/packages/tca-layout/global.d.ts @@ -1,58 +1,17 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - declare module '*.scss'; declare module '*.svg'; declare module '*.png'; declare module '*.ico'; -type Store = import('redux').Store; -type Reducer = import('redux').Reducer; - -interface LifeCycle { - bootstrap: (config: T) => void; - mount: (config: T) => void; - unmount: (config: T) => void; - update?: (config: T) => void; -} - -type RegisterMicroApp = (id: string, lifecycle: LifeCycle) => void; -type TInjectAsyncReducer = (name: string, reducer: Reducer, override?: boolean) => void; - -interface MicroApplicationProps { - name: string; - description: string; - match: string; - commitId?: string; - changeAt?: string; - css: string[]; - js: string[]; - prefix: string[] | string; -} - -interface MicroApplication { - props: MicroApplicationProps; - readonly loadStyle: () => Promise; - readonly loadScript: () => Promise; - readonly loadResources: () => Promise; - readonly removeStyle: () => Promise; - readonly path: () => RegExp; -} - -interface WindowMicroHook { - registerApp: RegisterMicroApp; - injectAsyncReducer: TInjectAsyncReducer; - store: Store; - meta: MicroApplication[]; -} +declare const ENABLE_MANAGE: boolean; interface Window { microHook: WindowMicroHook; } -declare const PLATFORM_ENV: 'saas' | 'private' | 'oa'; - -declare const ENABLE_MANAGE: 'TRUE'; +interface RestfulListAPIParams { + results: any[]; + count: number; + next: string; + previous: string +} diff --git a/web/packages/tca-layout/i18next-scanner.config.js b/web/packages/tca-layout/i18next-scanner.config.js new file mode 100644 index 000000000..f0e136f4e --- /dev/null +++ b/web/packages/tca-layout/i18next-scanner.config.js @@ -0,0 +1,2 @@ +const { i18nScannerConfig } = require('@tencent/micro-frontend-shared/i18n/i18next-scanner.config'); +module.exports = i18nScannerConfig; diff --git a/web/packages/tca-layout/package.json b/web/packages/tca-layout/package.json index 0502072db..5dad7d8ac 100644 --- a/web/packages/tca-layout/package.json +++ b/web/packages/tca-layout/package.json @@ -7,14 +7,20 @@ "micro-frontend" ], "license": "MIT", + "main": "src/index.tsx", + "files": [ + "src" + ], "scripts": { - "dev": "NODE_ENV=development webpack server --config ./scripts/webpack.dev.js --progress --color", - "build": "NODE_ENV=production webpack --config ./scripts/webpack.prod.js --progress --color", + "dev": "PLATFORM_ENV=${PLATFORM_ENV:-open} ENABLE_MANAGE=${ENABLE_MANAGE:-false} PUBLIC_PATH=${PUBLIC_PATH:-http://127.0.0.1:5056/} PORT=${PORT:-5056} NODE_ENV=development webpack server --config ./webpack.config.ts --progress --color", + "build": "NODE_ENV=production webpack --config ./webpack.config.ts --progress --color", "analyzer": "webpack-bundle-analyzer --port 8888 ./dist/stats.json", - "lint": "eslint --ext .js,.jsx,.ts,.tsx src/", - "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx src/ --fix" + "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", + "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --fix", + "scanner": "i18next-scanner" }, "dependencies": { + "@tencent/micro-frontend-shared": "^1.0.0", "@types/lodash": "^4.14.175", "@types/qs": "^6.9.7", "@types/react": "^17.0.24", @@ -23,53 +29,22 @@ "@types/react-redux": "^7.1.18", "@types/react-router-dom": "^5.3.1", "classnames": "^2.3.1", - "coding-oa-uikit": "^4.3.9", + "coding-oa-uikit": "^4.3.10", "i18next": "^21.2.4", "lodash": "^4.17.21", - "moment": "2.29.4", + "moment": "^2.29.4", "qs": "^6.10.1", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.4", "react-dom": "^17.0.2", - "react-i18next": "^11.12.0", - "react-markdown": "^8.0.3", + "react-i18next": "^11.17.3", + "react-markdown": "^7.0.1", + "react-piwik": "^1.12.0", "react-redux": "^7.2.5", "react-router-dom": "^5.3.0", "universal-cookie": "^4.0.4" }, "devDependencies": { - "@babel/core": "^7.15.5", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.15.6", - "@babel/plugin-transform-runtime": "^7.15.0", - "@babel/preset-env": "^7.15.6", - "@babel/preset-react": "^7.14.5", - "@babel/preset-typescript": "^7.15.0", - "@hot-loader/react-dom": "^17.0.1", - "@types/friendly-errors-webpack-plugin": "^0.1.4", - "@types/mini-css-extract-plugin": "^2.3.0", - "@types/sass": "^1.16.1", - "assets-webpack-plugin": "^7.1.1", - "axios": "^0.22.0", - "babel-loader": "^8.2.2", - "clean-webpack-plugin": "^4.0.0", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.3.0", - "eslint-webpack-plugin": "^3.0.1", - "friendly-errors-webpack-plugin": "^1.7.0", - "html-webpack-plugin": "^5.3.2", - "mini-css-extract-plugin": "^2.3.0", - "postcss-loader": "^6.1.1", - "postcss-preset-env": "^6.7.0", - "react-hot-loader": "^4.13.0", - "sass": "^1.42.1", - "sass-loader": "^12.1.0", - "style-loader": "^3.3.0", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.2", - "webpack-cli": "^4.8.0", - "webpack-dev-server": "^4.3.0", - "webpack-merge": "^5.8.0", - "webpackbar": "^5.0.0-3" + "@tencent/micro-frontend-webpack": "^1.0.0" } } \ No newline at end of file diff --git a/web/packages/tca-layout/public/index.html b/web/packages/tca-layout/public/index.html index 61397c3db..da7a0ab29 100644 --- a/web/packages/tca-layout/public/index.html +++ b/web/packages/tca-layout/public/index.html @@ -15,8 +15,10 @@ -
-
+
+
+
+
\ No newline at end of file diff --git a/web/packages/tca-layout/public/locales/en-US/translation.json b/web/packages/tca-layout/public/locales/en-US/translation.json new file mode 100644 index 000000000..e546cb4d7 --- /dev/null +++ b/web/packages/tca-layout/public/locales/en-US/translation.json @@ -0,0 +1,262 @@ +{ + "负责人为必填项": "负责人为必填项", + "编辑": "编辑", + "成员数": "成员数", + "项目数": "项目数", + "代码库": "代码库", + "团队名称": "团队名称", + "团队概览": "团队概览", + "项目名称": "项目名称", + "创建时间": "创建时间", + "操作": "操作", + "昵称": "昵称", + "用户昵称为必填项": "用户昵称为必填项", + "立即体验": "立即体验", + "管理入口": "管理入口", + "开源地址": "开源地址", + "个人中心": "个人中心", + "凭证管理": "凭证管理", + "帮助文档": "帮助文档", + "退出登录中...": "退出登录中...", + "退出": "退出", + "语言切换中...": "语言切换中...", + "切换语言": "切换语言", + "团队切换中...": "团队切换中...", + "切换团队": "切换团队", + "工具管理": "工具管理", + "节点管理": "节点管理", + "仓库登记": "仓库登记", + "代码分析": "代码分析", + "分支项目": "分支项目", + "分析方案": "分析方案", + "分析方案模板": "分析方案模板", + "项目概览": "项目概览", + "项目成员": "项目成员", + "开放平台": "开放平台", + "工作台": "工作台", + "项目": "项目", + "团队成员": "团队成员", + "已更新凭证": "已更新凭证", + "已录入一条新凭证": "已录入一条新凭证", + "编辑凭证": "编辑凭证", + "录入凭证": "录入凭证", + "凭证类型": "凭证类型", + "凭证类型为必填项": "凭证类型为必填项", + "凭证名称": "凭证名称", + "凭证名称为必填项": "凭证名称为必填项", + "凭证名称不能超过32个字符": "凭证名称不能超过32个字符", + "请输入凭证名称,不超过32个字符": "请输入凭证名称,不超过32个字符", + "SSH 私钥": "SSH 私钥", + "SSH 私钥为必填项": "SSH 私钥为必填项", + "请输入SSH 私钥": "请输入SSH 私钥", + "用户名": "用户名", + "用户名为必填项": "用户名为必填项", + "用户名不能超过32个字符": "用户名不能超过32个字符", + "请输入用户名,不超过32个字符": "请输入用户名,不超过32个字符", + "密码": "密码", + "密码为必填项": "密码为必填项", + "密码不能超过64个字符": "密码不能超过64个字符", + "请输入密码,不超过64个字符": "请输入密码,不超过64个字符", + "凭证来源平台": "凭证来源平台", + "其他凭证来源平台说明": "其他凭证来源平台说明", + "凭证": "凭证", + "创建人": "创建人", + "已删除凭证": "已删除凭证", + "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。": "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。", + "删除凭证": "删除凭证", + "确认删除凭证": "确认删除凭证", + "?": "?", + "用户信息": "用户信息", + "城市": "城市", + "联系方式": "联系方式", + "创建日期": "创建日期", + "确定": "确定", + "取消": "取消", + "个人令牌": "个人令牌", + "邀请成员": "邀请成员", + "团队成员管理": "团队成员管理", + "复制链接": "复制链接", + "移除用户": "移除用户", + "团队信息": "团队信息", + "团队名称为必填项": "团队名称为必填项", + "团队地址": "团队地址", + "团队负责人": "团队负责人", + "团队负责人为必填项": "团队负责人为必填项", + "项目唯一标识": "项目唯一标识", + "项目唯一标识为必填项": "项目唯一标识为必填项", + "仅支持英文、数字、中划线或下划线": "仅支持英文、数字、中划线或下划线", + "项目名称为必填项": "项目名称为必填项", + "项目描述": "项目描述", + "创建团队": "创建团队", + "所有团队": "所有团队", + "团队信息审核失败": "团队信息审核失败", + "平台会在1-2个工作日内完成审核,请稍候": "平台会在1-2个工作日内完成审核,请稍候", + "联系电话为必填项": "联系电话为必填项", + "请输入合法的联系电话": "请输入合法的联系电话", + "OAuth授权成功": "OAuth授权成功", + "OAuth授权失败": "OAuth授权失败", + "OAuth授权中": "OAuth授权中", + "工具列表": "工具列表", + "工具依赖": "工具依赖", + "平台": "平台", + "创建渠道": "创建渠道", + "平台暂未配置OAuth应用,无法去授权,请联系管理员。": "平台暂未配置OAuth应用,无法去授权,请联系管理员。", + "节点列表": "节点列表", + "标签列表": "标签列表", + "已更新节点": "已更新节点", + "更新节点": "更新节点", + "节点名称": "节点名称", + "节点名称为必填项": "节点名称为必填项", + "节点标签为必选项": "节点标签为必选项", + "节点可用性为必选项": "节点可用性为必选项", + "管理员为必填项": "管理员为必填项", + "管理员": "管理员", + "关注人": "关注人", + "IP 地址": "IP 地址", + "最近上报心跳": "最近上报心跳", + "所属标签": "所属标签", + "节点状态": "节点状态", + "工具进程": "工具进程", + "任务列表": "任务列表", + "执行任务列表": "执行任务列表", + "任务": "任务", + "子任务": "子任务", + "执行状态": "执行状态", + "已更新该节点进程配置": "已更新该节点进程配置", + "节点信息": "节点信息", + "负责人": "负责人", + "节点配置信息": "节点配置信息", + "可用内存:": "可用内存:", + "可用硬盘:": "可用硬盘:", + "节点工具进程配置": "节点工具进程配置", + "保存节点工具进程配置": "保存节点工具进程配置", + "工具": "工具", + "已更新标签信息": "已更新标签信息", + "已创建标签": "已创建标签", + "更新标签": "更新标签", + "添加标签": "添加标签", + "标签名称": "标签名称", + "展示名称": "展示名称", + "展示名称为必填项": "展示名称为必填项", + "类型": "类型", + "标签类型为必选项": "标签类型为必选项", + "标签描述": "标签描述", + "描述": "描述", + "其他操作": "其他操作", + "团队已禁用!": "团队已禁用!", + "禁用": "禁用", + "团队": "团队", + "后续如需恢复团队,请联系平台管理员在管理后台恢复": "后续如需恢复团队,请联系平台管理员在管理后台恢复", + "团队唯一标识": "团队唯一标识", + "禁用团队": "禁用团队", + "创建成功": "创建成功", + "创建项目": "创建项目", + "滚动加载更多团队": "滚动加载更多团队", + "更新团队信息": "更新团队信息", + "工具名称": "工具名称", + "工具状态": "工具状态", + "仅查看自定义工具": "仅查看自定义工具", + "严重级别": "严重级别", + "规则类别": "规则类别", + "适用语言": "适用语言", + "规则状态": "规则状态", + "可用": "可用", + "不可用": "不可用", + "规则名称": "规则名称", + "创建工具": "创建工具", + "请输入工具名称!": "请输入工具名称!", + "工具展示名称": "工具展示名称", + "请输入前端展示名称!": "请输入前端展示名称!", + "请使用大驼峰命名,如PyLint。": "请使用大驼峰命名,如PyLint。", + "工具描述": "工具描述", + "长度限制256个字符。": "长度限制256个字符。", + "工具仓库地址": "工具仓库地址", + "请输入工具仓库地址": "请输入工具仓库地址", + "执行命令": "执行命令", + "请输入执行命令": "请输入执行命令", + "该命令的工作目录为工具库根目录。": "该命令的工作目录为工具库根目录。", + "环境变量": "环境变量", + "示例:PYTHON_HOME = $PYTHON#&_HOMEPATH = $PYTHON_HOME/bin:$PATH": "示例:PYTHON_HOME = $PYTHON#&_HOMEPATH = $PYTHON_HOME/bin:$PATH", + "许可证": "许可证", + "是否为编译型工具": "是否为编译型工具", + "修改成功": "修改成功", + "确认修改运营状态?": "确认修改运营状态?", + "请选择运营状态": "请选择运营状态", + "运营状态修改成功": "运营状态修改成功", + "其他": "其他", + "运营状态": "运营状态", + "修改运营状态": "修改运营状态", + "请输入工具描述!": "请输入工具描述!", + "语言": "语言", + "负责团队": "负责团队", + "确认": "确认", + "基础信息": "基础信息", + "依赖配置": "依赖配置", + "规则列表": "规则列表", + "自定义规则": "自定义规则", + "工具白名单": "工具白名单", + "确定删除该依赖配置?": "确定删除该依赖配置?", + "删除成功": "删除成功", + "适用于": "适用于", + "系统": "系统", + "所有条件均不满足时使用该方案": "所有条件均不满足时使用该方案", + "默认方案": "默认方案", + "删除": "删除", + "适用条件:": "适用条件:", + "工具依赖:": "工具依赖:", + "环境变量:": "环境变量:", + "变量名": "变量名", + "变量值": "变量值", + "Tips:": "Tips:", + "1. 每个依赖加载后提供的环境变量。": "1. 每个依赖加载后提供的环境变量。", + "2. $ROOT_DIR 表示依赖仓库拉取到本地后的目录路径,会替换成每个依赖目录的实际路径。": "2. $ROOT_DIR 表示依赖仓库拉取到本地后的目录路径,会替换成每个依赖目录的实际路径。", + "添加依赖配置": "添加依赖配置", + "依赖方案编辑成功": "依赖方案编辑成功", + "依赖方案添加成功": "依赖方案添加成功", + "添加": "添加", + "判断条件": "判断条件", + "当环境变量满足该条件时使用当前依赖,如果不需要区分,可以不填。示例:设置判断条件PYTHON_VERSION=3时,使用python3依赖。": "当环境变量满足该条件时使用当前依赖,如果不需要区分,可以不填。示例:设置判断条件PYTHON_VERSION=3时,使用python3依赖。", + "适用系统": "适用系统", + "选择当前方案适用的操作系统": "选择当前方案适用的操作系统", + "请选择工具依赖": "请选择工具依赖", + "选择当前方案需要加载的工具依赖": "选择当前方案需要加载的工具依赖", + "请先选择适用系统": "请先选择适用系统", + "暂无数据": "暂无数据", + "必须有一个默认方案,可设置其他方案为默认方案来切换默认方案": "必须有一个默认方案,可设置其他方案为默认方案来切换默认方案", + "确定删除": "确定删除", + "添加规则": "添加规则", + "规则简介": "规则简介", + "分类": "分类", + "通用": "通用", + "状态": "状态", + "规则详情": "规则详情", + "规则分类": "规则分类", + "规则参数": "规则参数", + "解决方法": "解决方法", + "详细描述": "详细描述", + "编辑规则": "编辑规则", + "创建规则": "创建规则", + "规则唯一标识": "规则唯一标识", + "请输入规则名称": "请输入规则名称", + "请输入展示名称": "请输入展示名称", + "请采用大驼峰命名,eg:FilesNotFound": "请采用大驼峰命名,eg:FilesNotFound", + "请输入规则描述": "请输入规则描述", + "简要描述规则的功能": "简要描述规则的功能", + "请输入规则详细描述": "请输入规则详细描述", + "详细描述规则": "详细描述规则", + "类别": "类别", + "请选择类别": "请选择类别", + "请选择严重级别": "请选择严重级别", + "默认为通用": "默认为通用", + "请输入解决方法": "请输入解决方法", + "是否失效": "是否失效", + "失效原因": "失效原因", + "请输入失效原因": "请输入失效原因", + "添加成功": "添加成功", + "添加白名单": "添加白名单", + "需要编译": "需要编译", + "表示该工具可自定义规则": "表示该工具可自定义规则", + "协同": "协同", + "由本团队创建的工具": "由本团队创建的工具", + "自定义": "自定义" +} diff --git a/web/packages/tca-layout/public/locales/zh-CN/translation.json b/web/packages/tca-layout/public/locales/zh-CN/translation.json new file mode 100644 index 000000000..e546cb4d7 --- /dev/null +++ b/web/packages/tca-layout/public/locales/zh-CN/translation.json @@ -0,0 +1,262 @@ +{ + "负责人为必填项": "负责人为必填项", + "编辑": "编辑", + "成员数": "成员数", + "项目数": "项目数", + "代码库": "代码库", + "团队名称": "团队名称", + "团队概览": "团队概览", + "项目名称": "项目名称", + "创建时间": "创建时间", + "操作": "操作", + "昵称": "昵称", + "用户昵称为必填项": "用户昵称为必填项", + "立即体验": "立即体验", + "管理入口": "管理入口", + "开源地址": "开源地址", + "个人中心": "个人中心", + "凭证管理": "凭证管理", + "帮助文档": "帮助文档", + "退出登录中...": "退出登录中...", + "退出": "退出", + "语言切换中...": "语言切换中...", + "切换语言": "切换语言", + "团队切换中...": "团队切换中...", + "切换团队": "切换团队", + "工具管理": "工具管理", + "节点管理": "节点管理", + "仓库登记": "仓库登记", + "代码分析": "代码分析", + "分支项目": "分支项目", + "分析方案": "分析方案", + "分析方案模板": "分析方案模板", + "项目概览": "项目概览", + "项目成员": "项目成员", + "开放平台": "开放平台", + "工作台": "工作台", + "项目": "项目", + "团队成员": "团队成员", + "已更新凭证": "已更新凭证", + "已录入一条新凭证": "已录入一条新凭证", + "编辑凭证": "编辑凭证", + "录入凭证": "录入凭证", + "凭证类型": "凭证类型", + "凭证类型为必填项": "凭证类型为必填项", + "凭证名称": "凭证名称", + "凭证名称为必填项": "凭证名称为必填项", + "凭证名称不能超过32个字符": "凭证名称不能超过32个字符", + "请输入凭证名称,不超过32个字符": "请输入凭证名称,不超过32个字符", + "SSH 私钥": "SSH 私钥", + "SSH 私钥为必填项": "SSH 私钥为必填项", + "请输入SSH 私钥": "请输入SSH 私钥", + "用户名": "用户名", + "用户名为必填项": "用户名为必填项", + "用户名不能超过32个字符": "用户名不能超过32个字符", + "请输入用户名,不超过32个字符": "请输入用户名,不超过32个字符", + "密码": "密码", + "密码为必填项": "密码为必填项", + "密码不能超过64个字符": "密码不能超过64个字符", + "请输入密码,不超过64个字符": "请输入密码,不超过64个字符", + "凭证来源平台": "凭证来源平台", + "其他凭证来源平台说明": "其他凭证来源平台说明", + "凭证": "凭证", + "创建人": "创建人", + "已删除凭证": "已删除凭证", + "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。": "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。", + "删除凭证": "删除凭证", + "确认删除凭证": "确认删除凭证", + "?": "?", + "用户信息": "用户信息", + "城市": "城市", + "联系方式": "联系方式", + "创建日期": "创建日期", + "确定": "确定", + "取消": "取消", + "个人令牌": "个人令牌", + "邀请成员": "邀请成员", + "团队成员管理": "团队成员管理", + "复制链接": "复制链接", + "移除用户": "移除用户", + "团队信息": "团队信息", + "团队名称为必填项": "团队名称为必填项", + "团队地址": "团队地址", + "团队负责人": "团队负责人", + "团队负责人为必填项": "团队负责人为必填项", + "项目唯一标识": "项目唯一标识", + "项目唯一标识为必填项": "项目唯一标识为必填项", + "仅支持英文、数字、中划线或下划线": "仅支持英文、数字、中划线或下划线", + "项目名称为必填项": "项目名称为必填项", + "项目描述": "项目描述", + "创建团队": "创建团队", + "所有团队": "所有团队", + "团队信息审核失败": "团队信息审核失败", + "平台会在1-2个工作日内完成审核,请稍候": "平台会在1-2个工作日内完成审核,请稍候", + "联系电话为必填项": "联系电话为必填项", + "请输入合法的联系电话": "请输入合法的联系电话", + "OAuth授权成功": "OAuth授权成功", + "OAuth授权失败": "OAuth授权失败", + "OAuth授权中": "OAuth授权中", + "工具列表": "工具列表", + "工具依赖": "工具依赖", + "平台": "平台", + "创建渠道": "创建渠道", + "平台暂未配置OAuth应用,无法去授权,请联系管理员。": "平台暂未配置OAuth应用,无法去授权,请联系管理员。", + "节点列表": "节点列表", + "标签列表": "标签列表", + "已更新节点": "已更新节点", + "更新节点": "更新节点", + "节点名称": "节点名称", + "节点名称为必填项": "节点名称为必填项", + "节点标签为必选项": "节点标签为必选项", + "节点可用性为必选项": "节点可用性为必选项", + "管理员为必填项": "管理员为必填项", + "管理员": "管理员", + "关注人": "关注人", + "IP 地址": "IP 地址", + "最近上报心跳": "最近上报心跳", + "所属标签": "所属标签", + "节点状态": "节点状态", + "工具进程": "工具进程", + "任务列表": "任务列表", + "执行任务列表": "执行任务列表", + "任务": "任务", + "子任务": "子任务", + "执行状态": "执行状态", + "已更新该节点进程配置": "已更新该节点进程配置", + "节点信息": "节点信息", + "负责人": "负责人", + "节点配置信息": "节点配置信息", + "可用内存:": "可用内存:", + "可用硬盘:": "可用硬盘:", + "节点工具进程配置": "节点工具进程配置", + "保存节点工具进程配置": "保存节点工具进程配置", + "工具": "工具", + "已更新标签信息": "已更新标签信息", + "已创建标签": "已创建标签", + "更新标签": "更新标签", + "添加标签": "添加标签", + "标签名称": "标签名称", + "展示名称": "展示名称", + "展示名称为必填项": "展示名称为必填项", + "类型": "类型", + "标签类型为必选项": "标签类型为必选项", + "标签描述": "标签描述", + "描述": "描述", + "其他操作": "其他操作", + "团队已禁用!": "团队已禁用!", + "禁用": "禁用", + "团队": "团队", + "后续如需恢复团队,请联系平台管理员在管理后台恢复": "后续如需恢复团队,请联系平台管理员在管理后台恢复", + "团队唯一标识": "团队唯一标识", + "禁用团队": "禁用团队", + "创建成功": "创建成功", + "创建项目": "创建项目", + "滚动加载更多团队": "滚动加载更多团队", + "更新团队信息": "更新团队信息", + "工具名称": "工具名称", + "工具状态": "工具状态", + "仅查看自定义工具": "仅查看自定义工具", + "严重级别": "严重级别", + "规则类别": "规则类别", + "适用语言": "适用语言", + "规则状态": "规则状态", + "可用": "可用", + "不可用": "不可用", + "规则名称": "规则名称", + "创建工具": "创建工具", + "请输入工具名称!": "请输入工具名称!", + "工具展示名称": "工具展示名称", + "请输入前端展示名称!": "请输入前端展示名称!", + "请使用大驼峰命名,如PyLint。": "请使用大驼峰命名,如PyLint。", + "工具描述": "工具描述", + "长度限制256个字符。": "长度限制256个字符。", + "工具仓库地址": "工具仓库地址", + "请输入工具仓库地址": "请输入工具仓库地址", + "执行命令": "执行命令", + "请输入执行命令": "请输入执行命令", + "该命令的工作目录为工具库根目录。": "该命令的工作目录为工具库根目录。", + "环境变量": "环境变量", + "示例:PYTHON_HOME = $PYTHON#&_HOMEPATH = $PYTHON_HOME/bin:$PATH": "示例:PYTHON_HOME = $PYTHON#&_HOMEPATH = $PYTHON_HOME/bin:$PATH", + "许可证": "许可证", + "是否为编译型工具": "是否为编译型工具", + "修改成功": "修改成功", + "确认修改运营状态?": "确认修改运营状态?", + "请选择运营状态": "请选择运营状态", + "运营状态修改成功": "运营状态修改成功", + "其他": "其他", + "运营状态": "运营状态", + "修改运营状态": "修改运营状态", + "请输入工具描述!": "请输入工具描述!", + "语言": "语言", + "负责团队": "负责团队", + "确认": "确认", + "基础信息": "基础信息", + "依赖配置": "依赖配置", + "规则列表": "规则列表", + "自定义规则": "自定义规则", + "工具白名单": "工具白名单", + "确定删除该依赖配置?": "确定删除该依赖配置?", + "删除成功": "删除成功", + "适用于": "适用于", + "系统": "系统", + "所有条件均不满足时使用该方案": "所有条件均不满足时使用该方案", + "默认方案": "默认方案", + "删除": "删除", + "适用条件:": "适用条件:", + "工具依赖:": "工具依赖:", + "环境变量:": "环境变量:", + "变量名": "变量名", + "变量值": "变量值", + "Tips:": "Tips:", + "1. 每个依赖加载后提供的环境变量。": "1. 每个依赖加载后提供的环境变量。", + "2. $ROOT_DIR 表示依赖仓库拉取到本地后的目录路径,会替换成每个依赖目录的实际路径。": "2. $ROOT_DIR 表示依赖仓库拉取到本地后的目录路径,会替换成每个依赖目录的实际路径。", + "添加依赖配置": "添加依赖配置", + "依赖方案编辑成功": "依赖方案编辑成功", + "依赖方案添加成功": "依赖方案添加成功", + "添加": "添加", + "判断条件": "判断条件", + "当环境变量满足该条件时使用当前依赖,如果不需要区分,可以不填。示例:设置判断条件PYTHON_VERSION=3时,使用python3依赖。": "当环境变量满足该条件时使用当前依赖,如果不需要区分,可以不填。示例:设置判断条件PYTHON_VERSION=3时,使用python3依赖。", + "适用系统": "适用系统", + "选择当前方案适用的操作系统": "选择当前方案适用的操作系统", + "请选择工具依赖": "请选择工具依赖", + "选择当前方案需要加载的工具依赖": "选择当前方案需要加载的工具依赖", + "请先选择适用系统": "请先选择适用系统", + "暂无数据": "暂无数据", + "必须有一个默认方案,可设置其他方案为默认方案来切换默认方案": "必须有一个默认方案,可设置其他方案为默认方案来切换默认方案", + "确定删除": "确定删除", + "添加规则": "添加规则", + "规则简介": "规则简介", + "分类": "分类", + "通用": "通用", + "状态": "状态", + "规则详情": "规则详情", + "规则分类": "规则分类", + "规则参数": "规则参数", + "解决方法": "解决方法", + "详细描述": "详细描述", + "编辑规则": "编辑规则", + "创建规则": "创建规则", + "规则唯一标识": "规则唯一标识", + "请输入规则名称": "请输入规则名称", + "请输入展示名称": "请输入展示名称", + "请采用大驼峰命名,eg:FilesNotFound": "请采用大驼峰命名,eg:FilesNotFound", + "请输入规则描述": "请输入规则描述", + "简要描述规则的功能": "简要描述规则的功能", + "请输入规则详细描述": "请输入规则详细描述", + "详细描述规则": "详细描述规则", + "类别": "类别", + "请选择类别": "请选择类别", + "请选择严重级别": "请选择严重级别", + "默认为通用": "默认为通用", + "请输入解决方法": "请输入解决方法", + "是否失效": "是否失效", + "失效原因": "失效原因", + "请输入失效原因": "请输入失效原因", + "添加成功": "添加成功", + "添加白名单": "添加白名单", + "需要编译": "需要编译", + "表示该工具可自定义规则": "表示该工具可自定义规则", + "协同": "协同", + "由本团队创建的工具": "由本团队创建的工具", + "自定义": "自定义" +} diff --git a/web/packages/tca-layout/scripts/config-webpack-plugin.js b/web/packages/tca-layout/scripts/config-webpack-plugin.js deleted file mode 100644 index afc27e672..000000000 --- a/web/packages/tca-layout/scripts/config-webpack-plugin.js +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const AssetsWebpackPlugin = require('assets-webpack-plugin'); -const merge = require('lodash/merge'); -const chalk = require('chalk'); - -const PLUGIN_NAME = 'ConfigWebpackPlugin'; -const PLUGIN_PREFIX = `[${PLUGIN_NAME}] `; - -function isTrue(value) { - return value === true || value === 'true'; -} - -class ConfigWebpackPlugin { - constructor(options) { - if (!options) { - options = {}; - } - const productName = this.getProductName(options); - const description = this.getDescription(options); - this.options = merge( - { - enable: process.env.CONFIG_ENABLED || true, // 默认启用 - productName, - description, - commitId: process.env.GIT_REVISION || '', - match: process.env.PRODUCT_ROUTE_MATCH, - prefix: process.env.PUBLIC_PATH || '/', - }, - options, - ); - this.isDev = (!!options.isDev) || process.env.NODE_ENV !== 'production'; - - // AssetsWebpackPlugin所需 - this.path = options.path; - this.filename = `${productName}.json`; - this.assetKeys = options.assetKeys || []; - - // 未启用 - if (!isTrue(this.options.enable)) { - console.info(chalk.yellow(PLUGIN_PREFIX) - + chalk.green('plugin is disabled, please use process.env.CONFIG_ENABLED enable it')); - return; - } - this.optionCheck(this.options); - } - - // 对启用该插件进行必要参数校验 - optionCheck(options) { - if (!options.productName) { - throw new Error(`${PLUGIN_PREFIX} 需要设置 productName。const productName = options?.productName || options?.pkgInfo?.name || process.env.PRODUCT_NAME;`); - } - - if (!options.path) { - throw new Error(`${PLUGIN_PREFIX} 需要设置 path。用于AssetsWebpackPlugin打包资源到path下`); - } - - if (!options.assetKeys) { - throw new Error(`${PLUGIN_PREFIX} 需要设置 assetKeys。用于资源获取。`); - } - - if (!options.match) { - throw new Error(`${PLUGIN_PREFIX} 需要设置 match。用于资源路由match`); - } - } - - // 获取应用名称 - getProductName(options) { - if (options) { - if (options.productName) { - return options.productName; - } - if (options.pkgInfo?.name) { - return options.pkgInfo.name; - } - } - return process.env.PRODUCT_NAME; - } - - // 获取应用描述 - getDescription(options) { - if (options?.pkgInfo?.description) { - return options.pkgInfo.description; - } - return process.env.PRODUCT_DESC || ''; - } - - apply(compiler) { - const plugins = [ - new AssetsWebpackPlugin({ - path: this.path, - filename: this.filename, - processOutput: this.processOutput.bind(this), - }), - ]; - - plugins.forEach((plugin) => { - plugin.apply(compiler); - }); - - // 在 compilation 完成时执行,dev环境将配置地址打印出来 - compiler.hooks.done.tap(PLUGIN_NAME, (stats) => { - // 用于dev,生成api.json url - if (this.isDev) { - const { https = false, host = 'localhost', port = 8080 } = stats.compilation.options.devServer; - const reg = new RegExp(/https?:\/\//); - const publicPath = this.options.prefix; - const prefix = reg.test(publicPath) ? publicPath : `http${https ? 's' : ''}://${host}:${port}${publicPath}`; - const api = `${prefix}${this.filename}`; - setTimeout(() => { - console.info(`${chalk.yellow('[dev环境]')}: ${chalk.green(`API = ${chalk.yellow(api)} , `)}`); - }, 20); - } - }); - } - - processOutput(assets) { - // 插件未启用 - if (!isTrue(this.options.enable)) { - console.info(chalk.yellow(PLUGIN_PREFIX) + chalk.green('插件未启用,跳过...')); - return ''; - } - - // 获取资源内的js和css - const js = this.assetKeys.map(k => assets[k]?.js).filter(v => !!v); - const css = this.assetKeys.map(k => assets[k]?.css).filter(v => !!v); - - // 生成config - const config = { - name: this.options.productName, - description: this.options.description, - commitId: this.options.commitId, - match: this.options.match, - js, - css, - prefix: [this.options.prefix], - }; - - console.log(chalk.yellow(PLUGIN_PREFIX) + chalk.yellow('[config]') + chalk.green(JSON.stringify(config))); - return this.options.processOutput ? this.options.processOutput(assets, config) : JSON.stringify(config); - } -} - -module.exports = ConfigWebpackPlugin; diff --git a/web/packages/tca-layout/scripts/envs.js b/web/packages/tca-layout/scripts/envs.js deleted file mode 100644 index 58b91bbc9..000000000 --- a/web/packages/tca-layout/scripts/envs.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const envs = { - PUBLIC_PATH: process.env.PUBLIC_PATH || '/', - TITLE: process.env.TITLE, - DESCRIPTION: process.env.DESCRIPTION, - KEYWORDS: process.env.KEYWORDS, - FAVICON: process.env.FAVICON, -}; - -// 用于生成index.runtime.html 可被替换的值 -const runtimeKeys = ['TITLE', 'DESCRIPTION', 'KEYWORDS', 'FAVICON']; - -const runtimeEnvs = {}; - -runtimeKeys.forEach((key) => { - runtimeEnvs[key] = `__${key}__`; -}); - -module.exports = { - envs, - runtimeEnvs, -}; diff --git a/web/packages/tca-layout/scripts/webpack.common.js b/web/packages/tca-layout/scripts/webpack.common.js deleted file mode 100644 index 0d10d6b8f..000000000 --- a/web/packages/tca-layout/scripts/webpack.common.js +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const path = require('path'); -const webpack = require('webpack'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const EslintWebpackPlugin = require('eslint-webpack-plugin'); -// 日志优化 -const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); -const WebpackBar = require('webpackbar'); -const ConfigWebpackPlugin = require('./config-webpack-plugin'); - -const pkgInfo = require('../package.json'); - -// 根据NODE_ENV分别获取不同的config -const isDev = process.env.NODE_ENV === 'development'; -// 获取项目环境变量 -const { envs, runtimeEnvs } = require('./envs'); -// 打包目录路径 -const BASE_DIR = path.resolve(__dirname, '..'); -const buildPath = process.env.ENABLE_MANAGE === 'TRUE' ? path.resolve(BASE_DIR, 'dist-admin') : path.resolve(BASE_DIR, 'dist'); -// index.html路径 -const indexPath = path.resolve(BASE_DIR, 'public', 'index.html'); - -const htmlMinify = { - html5: true, // 根据HTML5规范解析输入 - collapseWhitespace: true, // 折叠空白区域 - preserveLineBreaks: false, - minifyCSS: true, // 压缩文内css - minifyJS: true, // 压缩文内js - removeComments: true, // 移除注释 -}; - -module.exports = { - entry: { - [pkgInfo.name]: path.resolve(BASE_DIR, 'src/index.tsx'), - }, - output: { - path: buildPath, - publicPath: process.env.PUBLIC_PATH || '/', - filename: `[name]${isDev ? '' : '-[chunkhash:8]'}.js`, - chunkFilename: `[name]${isDev ? '' : '-[chunkhash:8]'}.js`, - }, - devtool: isDev ? 'inline-source-map' : false, - target: 'web', - resolve: { - // 尝试按顺序解析这些后缀名 - extensions: ['.ts', '.tsx', '.js', '.jsx', '.svg'], - alias: { - '@src': path.resolve(BASE_DIR, 'src'), - 'react-dom': '@hot-loader/react-dom', - }, - modules: [BASE_DIR, 'node_modules'], - }, - module: { - rules: [ - { - test: /\.[jt]sx?$/i, - exclude: /node_modules/, - loader: 'babel-loader', - options: { - rootMode: 'upward', - }, - }, - // Images - { - test: /\.(?:ico|gif|png|jpg|jpeg)$/i, - type: 'asset/resource', - }, - // Fonts and SVGs - { - test: /\.(woff(2)?|eot|ttf|otf|svg|)$/i, - type: 'asset/inline', - }, - { - test: /\.css$/i, - use: [ - MiniCssExtractPlugin.loader, - 'css-loader', - ], - }, - { - test: /\.s[ac]ss$/i, - exclude: [path.resolve(BASE_DIR, 'public')], - use: [ - MiniCssExtractPlugin.loader, - // 将 CSS 转化成 CommonJS 模块 - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[local]-[hash:base64:10]', - exportLocalsConvention: 'camelCase', - }, - importLoaders: 2, - }, - }, - // 将 Sass 编译成 CSS - { - loader: 'sass-loader', - options: { - // Prefer `dart-sass` - implementation: require('sass'), - }, - }, - ], - }, - ], - }, - optimization: { - runtimeChunk: true, - splitChunks: { - chunks: 'all', - name: (module, chunks, cacheGroupKey) => { - const allChunksNames = chunks.map(item => item.name).join('~'); - return `${cacheGroupKey}~${allChunksNames}`; - }, - cacheGroups: { - vendors: { - test: /[\\/]node_modules[\\/]/, - chunks: 'all', - enforce: true, - }, - }, - }, - }, - plugins: [ - // 打包前移除/清理 打包目录 - new FriendlyErrorsWebpackPlugin(), - new CleanWebpackPlugin(), - new webpack.DefinePlugin({ - 'process.env': Object.keys(envs).reduce((e, key) => { - e[key] = JSON.stringify(envs[key]); - return e; - }, {}), - PLATFORM_ENV: JSON.stringify(process.env.PLATFORM_ENV), - ENABLE_MANAGE: JSON.stringify(process.env.ENABLE_MANAGE), - }), - new EslintWebpackPlugin({ - fix: true, - extensions: ['js', 'jsx', 'tsx', 'ts'], - }), - new MiniCssExtractPlugin({ - filename: `[name]${isDev ? '' : '-[contenthash:8]'}.css`, - chunkFilename: `[name]${isDev ? '' : '-[contenthash:8]'}.css`, - ignoreOrder: false, - }), - new HtmlWebpackPlugin({ - inject: true, - template: indexPath, - envs, - minify: htmlMinify, - }), - // 该配置生成一个 index.runtime.html 模板用于提供 index.html runtime 的能力 - new HtmlWebpackPlugin({ - inject: true, - template: indexPath, - filename: 'index.runtime.html', - minify: htmlMinify, - envs: { - ...envs, - ...runtimeEnvs, - }, - }), - new ConfigWebpackPlugin({ - pkgInfo, - isDev, - path: buildPath, - match: process.env.PRODUCT_ROUTE_MATCH || '/', - assetKeys: ['runtime~tca-layout', 'vendors~tca-layout', 'tca-layout'], - }), - // 忽略第三方包指定目录,让这些指定目录不要被打包进去,对moment操作参考:https://blog.csdn.net/qq_17175013/article/details/86845624 - new webpack.IgnorePlugin({ - resourceRegExp: /^\.\/locale$/, - contextRegExp: /moment$/, - }), - new WebpackBar(), - ], -}; diff --git a/web/packages/tca-layout/scripts/webpack.dev.js b/web/packages/tca-layout/scripts/webpack.dev.js deleted file mode 100644 index b13a873e9..000000000 --- a/web/packages/tca-layout/scripts/webpack.dev.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const path = require('path'); -const { merge } = require('webpack-merge'); -const common = require('./webpack.common.js'); -const host = process.env.HOST || '127.0.0.1'; -const port = process.env.PORT || 5056; -const webSocketURL = `ws://${host}:${port}/ws`; -module.exports = merge(common, { - devServer: { - static: path.join(__dirname, '../dist'), - hot: true, - liveReload: false, - allowedHosts: 'all', - host, - port, - client: { - webSocketURL, - }, - historyApiFallback: true, - compress: true, - devMiddleware: { - writeToDisk: true, - }, - headers: { - 'Access-Control-Allow-Origin': '*', - }, - }, -}); diff --git a/web/packages/tca-layout/scripts/webpack.prod.js b/web/packages/tca-layout/scripts/webpack.prod.js deleted file mode 100644 index c84bed2ab..000000000 --- a/web/packages/tca-layout/scripts/webpack.prod.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -const { merge } = require('webpack-merge'); -// 文件体积监控 -const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); - -const common = require('./webpack.common.js'); - -const externals = process.env.ENABLE_EXTERNALS === 'TRUE' ? { - react: 'React', - 'react-dom': 'ReactDOM', - 'react-redux': 'ReactRedux', - classnames: 'Classnames', - 'coding-oa-uikit': 'CodingOAUikit', - lodash: 'Lodash', -} : {}; - -module.exports = merge(common, { - performance: { - hints: false, - }, - plugins: [ - new BundleAnalyzerPlugin({ - analyzerMode: 'disabled', // 不启动展示打包报告的http服务器 - generateStatsFile: true, // 不打开网站,但是在dist生成stats.json文件 - }), - ], - externals, -}); diff --git a/web/packages/tca-layout/src/common/constants/authority.ts b/web/packages/tca-layout/src/common/constants/authority.ts deleted file mode 100644 index de5d0525b..000000000 --- a/web/packages/tca-layout/src/common/constants/authority.ts +++ /dev/null @@ -1,43 +0,0 @@ - -import { t } from '@src/i18n/i18next'; - -/** - * 凭证类型 - */ - export const AUTH_TYPE = { - HTTP: 'password', - SSH: 'ssh_token', - OAUTH: 'oauth', -}; - -export const AUTH_TYPE_TXT = { - HTTP: t('用户名 + 密码'), - SSH: t('ssh'), - OAUTH: t('OAuth'), -}; - -// 平台类型 -enum SCM_PLATFORM_ENUM { - OTHER = 1, - TGIT, - CODING, - GITHUB, - GITEE, - GITLAB -} - -export const SCM_PLATFORM = { - [SCM_PLATFORM_ENUM.OTHER]: t('其他'), - [SCM_PLATFORM_ENUM.TGIT]: t('腾讯工蜂'), - [SCM_PLATFORM_ENUM.CODING]: t('CODING'), - [SCM_PLATFORM_ENUM.GITHUB]: t('GitHub'), - [SCM_PLATFORM_ENUM.GITEE]: t('Gitee'), - [SCM_PLATFORM_ENUM.GITLAB]: t('GitLab'), -}; - -// 凭证映射,对应 api 返回的字段名 -export const SCM_MAP = { - [AUTH_TYPE.HTTP]: 'scm_account', - [AUTH_TYPE.SSH]: 'scm_ssh', - [AUTH_TYPE.OAUTH]: 'scm_oauth' -} \ No newline at end of file diff --git a/web/packages/tca-layout/src/common/constants/index.ts b/web/packages/tca-layout/src/common/constants/index.ts deleted file mode 100644 index 2639607e2..000000000 --- a/web/packages/tca-layout/src/common/constants/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -// 分页默认值 -export const DEFAULT_PAGER = { - count: 0, - pageSize: 10, - pageStart: 0, -}; - -export const BASE_ROUTE_PREFIX = '/code-analysis/repos/:repoId?'; - -export const PROJECT_ROUTE_PREFIX = `${BASE_ROUTE_PREFIX}/projects/:projectId`; diff --git a/web/packages/tca-layout/src/common/style/color.scss b/web/packages/tca-layout/src/common/style/color.scss deleted file mode 100644 index fd6a96779..000000000 --- a/web/packages/tca-layout/src/common/style/color.scss +++ /dev/null @@ -1,102 +0,0 @@ -$grey-1: #f5f7fa; -$grey-2: #e6e9ed; -$grey-3: #dadfe6; -$grey-4: #c5cedb; -$grey-5: #adbacc; -$grey-6: #8592a6; -$grey-7: #606c80; -$grey-8: #202d40; -$grey-9: #171d26; - -$blue-1: #e6f7ff; -$blue-2: #cceaff; -$blue-3: #8cc6ff; -$blue-4: #3d98ff; -$blue-5: #06f; -$blue-6: #0052cc; -$blue-7: #0f4799; -$blue-8: #1d4073; - -$red-1: #fff0f0; -$red-2: #fed2d2; -$red-3: #fc9c9c; -$red-4: #f76469; -$red-5: #eb333f; -$red-6: #ca1628; -$red-7: #9a1325; -$red-8: #791122; - -$orange-1: #fff4e0; -$orange-2: #ffe0b3; -$orange-3: #fec57c; -$orange-4: #fba337; -$orange-5: #f0850a; -$orange-6: #cb6b0b; -$orange-7: #9e540a; -$orange-8: #7b4209; - -$yellow-1: #fffbe5; -$yellow-2: #fff4c2; -$yellow-3: #fde586; -$yellow-4: #fbd341; -$yellow-5: #edb807; -$yellow-6: #ce9c09; -$yellow-7: #a07708; -$yellow-8: #725409; - -$green-1: #f2ffe0; -$green-2: #dbfdb5; -$green-3: #adf269; -$green-4: #7ad93a; -$green-5: #4fbe0e; -$green-6: #3ea00e; -$green-7: #2e7d0c; -$green-8: #205c0a; - -$cyan-1: #e5feff; -$cyan-2: #c4fafd; -$cyan-3: #8ef3fa; -$cyan-4: #3de6f5; -$cyan-5: #0ccadf; -$cyan-6: #0ba4bc; -$cyan-7: #097c90; -$cyan-8: #096072; - -$purple-1: #f4e5ff; -$purple-2: #dbb5fd; -$purple-3: #c28bf9; -$purple-4: #a657f4; -$purple-5: #892aef; -$purple-6: #6812ca; -$purple-7: #4b109e; -$purple-8: #380d77; - -$black: #000000; -$white: #ffffff; - -$fatal-bg: rgba( - $color: $red-5, - $alpha: 0.1, -); -$error-bg: rgba( - $color: $red-8, - $alpha: 0.07, -); -$warging-bg: rgba( - $color: $yellow-7, - $alpha: 0.08, -); -$success-bg: rgba( - $color: $green-8, - $alpha: 0.08, -); -$tip-bg: rgba( - $color: $blue-7, - $alpha: 0.08, -); - -$fatal-color: $red-5; -$error-color: $red-8; -$warging-color: $yellow-7; -$success-color: $green-7; -$tip-color: $blue-7; diff --git a/web/packages/tca-layout/src/common/style/common.scss b/web/packages/tca-layout/src/common/style/common.scss deleted file mode 100644 index 286a63dad..000000000 --- a/web/packages/tca-layout/src/common/style/common.scss +++ /dev/null @@ -1,690 +0,0 @@ -@import "./color.scss"; -@import "./font.scss"; -@import "./reset.scss"; - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -$space-base: 16px !default; -$space-x-base: $space-base !default; -$space-y-base: $space-base !default; - -$space-none: ( - x: 0, - y: 0, -) !default; -$space-xs: ( - x: ( - $space-x-base * 0.25, - ), - y: ( - $space-y-base * 0.25, - ), -) !default; -$space-sm: ( - x: ( - $space-x-base * 0.5, - ), - y: ( - $space-y-base * 0.5, - ), -) !default; -$space-md: ( - x: $space-x-base, - y: $space-y-base, -) !default; -$space-lg: ( - x: ( - $space-x-base * 1.5, - ), - y: ( - $space-y-base * 1.5, - ), -) !default; -$space-xl: ( - x: ( - $space-x-base * 3, - ), - y: ( - $space-y-base * 3, - ), -) !default; -$space-12: ( - x: 12px, - y: 12px, -) !default; -$space-20: ( - x: 20px, - y: 20px, -) !default; -$space-48: ( - x: 48px, - y: 48px, -) !default; -$space-6: ( - x: 6px, - y: 6px, -) !default; - -// sorry for long line; we need .sass and it doesn't support multi-line list -$spaces: ( - "none": $space-none, - "xs": $space-xs, - "6": $space-6, - "sm": $space-sm, - "md": $space-md, - "lg": $space-lg, - "xl": $space-xl, - "12": $space-12, - "20": $space-20, - "48": $space-48, -) !default; - -@each $space, $value in $spaces { - .pa-#{$space} { - padding: map-get($value, "y") map-get($value, "x"); - } - - .pl-#{$space} { - padding-left: map-get($value, "x"); - } - - .pr-#{$space} { - padding-right: map-get($value, "x"); - } - - .pt-#{$space} { - padding-top: map-get($value, "y"); - } - - .pb-#{$space} { - padding-bottom: map-get($value, "y"); - } - - .px-#{$space} { - padding-left: map-get($value, "x"); - padding-right: map-get($value, "x"); - } - - .py-#{$space} { - padding-top: map-get($value, "y"); - padding-bottom: map-get($value, "y"); - } - - .ma-#{$space} { - margin: map-get($value, "y") map-get($value, "x"); - } - - .ml-#{$space} { - margin-left: map-get($value, "x"); - } - - .mr-#{$space} { - margin-right: map-get($value, "x"); - } - - .mt-#{$space} { - margin-top: map-get($value, "y"); - } - - .mb-#{$space} { - margin-bottom: map-get($value, "y"); - } - - .mx-#{$space} { - margin-left: map-get($value, "x"); - margin-right: map-get($value, "x"); - } - - .my-#{$space} { - margin-top: map-get($value, "y"); - margin-bottom: map-get($value, "y"); - } -} - -.ml-auto { - margin-left: auto; -} - -.mr-auto { - margin-right: auto; -} - -.mx-auto { - margin-left: auto; - margin-right: auto; -} - -.block { - display: block !important; -} - -.inline-block { - display: inline-block !important; -} - -.fit { - width: 100% !important; - height: 100% !important; -} - -.full-height { - height: 100% !important; -} - -.full-width { - width: 100% !important; - margin-left: 0 !important; - margin-right: 0 !important; -} - -// visibility -.no-margin { - margin: 0 !important; -} - -.no-padding { - padding: 0 !important; -} - -.no-border { - border: 0 !important; -} - -.no-border-radius { - border-radius: 0 !important; -} - -.no-box-shadow { - box-shadow: none !important; -} - -.no-outline { - outline: 0 !important; -} - -.ellipsis { - text-overflow: ellipsis; - - white-space: nowrap; - - overflow: hidden; - - &-2-lines, - &-3-lines { - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - } - - &-2-lines { - -webkit-line-clamp: 2; - } - - &-3-lines { - -webkit-line-clamp: 3; - } -} - -.hidden { - display: none !important; -} - -.invisible { - visibility: hidden !important; -} - -.transparent { - background: transparent !important; -} - -.overflow-auto { - overflow: auto !important; -} - -.overflow-hidden { - overflow: hidden !important; -} - -.overflow-hidden-y { - overflow-y: hidden !important; -} - -$z-top: 7000 !default; -$z-max: 9998 !default; - -.z-top { - z-index: $z-top !important; -} - -.z-max { - z-index: $z-max !important; -} - -// mouse -.non-selectable { - user-select: none !important; -} - -.scroll { - overflow: auto; -} - -.scroll, -.scroll-x, -.scroll-y { - -webkit-overflow-scrolling: touch; - will-change: scroll-position; -} - -.scroll-x { - overflow-x: auto; -} - -.scroll-y { - overflow-y: auto; -} - -.no-scroll { - overflow: hidden !important; -} - -.no-pointer-events, -.no-pointer-events--children, -.no-pointer-events--children * { - pointer-events: none !important; -} - -.all-pointer-events { - pointer-events: all !important; -} - -.cursor { - &-pointer { - cursor: pointer !important; - } - - &-not-allowed { - cursor: not-allowed !important; - } - - &-inherit { - cursor: inherit !important; - } - - &-none { - cursor: none !important; - } -} - -// position -.float-left { - float: left; -} - -.float-right { - float: right; -} - -.relative-position { - position: relative; -} - -.absolute, -.absolute-full, -.absolute-center, -.absolute-bottom, -.absolute-left, -.absolute-right, -.absolute-top, -.absolute-top-left, -.absolute-top-right, -.absolute-bottom-left, -.absolute-bottom-right { - position: absolute; -} - -.fixed, -.fixed-full, -.fullscreen, -.fixed-center, -.fixed-bottom, -.fixed-left, -.fixed-right, -.fixed-top, -.fixed-top-left, -.fixed-top-right, -.fixed-bottom-left, -.fixed-bottom-right { - position: fixed; -} - -.fixed-center, -.absolute-center { - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} - -.fixed-top, -.absolute-top { - top: 0; - left: 0; - right: 0; -} - -.fixed-right, -.absolute-right { - top: 0; - right: 0; - bottom: 0; -} - -.fixed-bottom, -.absolute-bottom { - right: 0; - bottom: 0; - left: 0; -} - -.fixed-left, -.absolute-left { - top: 0; - bottom: 0; - left: 0; -} - -.fixed-top-left, -.absolute-top-left { - top: 0; - left: 0; -} - -.fixed-top-right, -.absolute-top-right { - top: 0; - right: 0; -} - -.fixed-bottom-left, -.absolute-bottom-left { - bottom: 0; - left: 0; -} - -.fixed-bottom-right, -.absolute-bottom-right { - bottom: 0; - right: 0; -} - -.vertical- { - &top { - vertical-align: top !important; - } - - &middle { - vertical-align: middle !important; - } - - &bottom { - vertical-align: bottom !important; - } -} - -.on-left { - margin-right: 12px; -} - -.on-right { - margin-left: 12px; -} - -$text-color: $grey-8; - -.text-black { - color: $black; -} - -.text-white { - color: $white; -} - -.bg-white { - background-color: $white; -} - -// grey -.text-grey-9 { - color: $grey-9; -} -.text-grey-8 { - color: $grey-8; -} -.text-grey-7 { - color: $grey-7; -} -.text-grey-6 { - color: $grey-6; -} -.text-grey-5 { - color: $grey-5; -} -.text-grey-4 { - color: $grey-4; -} -.text-grey-3 { - color: $grey-3; -} -.text-grey-2 { - color: $grey-2; -} -.text-grey-1 { - color: $grey-1; -} - -// blue -.text-blue-8 { - color: $blue-8; -} -.text-blue-7 { - color: $blue-7; -} -.text-blue-6 { - color: $blue-6; -} -.text-blue-5 { - color: $blue-5; -} -.text-blue-4 { - color: $blue-4; -} -.text-blue-3 { - color: $blue-3; -} -.text-blue-2 { - color: $blue-2; -} -.text-blue-1 { - color: $blue-1; -} - -// red -.text-red-8 { - color: $red-8; -} -.text-red-7 { - color: $red-7; -} -.text-red-6 { - color: $red-6; -} -.text-red-5 { - color: $red-5; -} -.text-red-4 { - color: $red-4; -} -.text-red-3 { - color: $red-3; -} -.text-red-2 { - color: $red-2; -} -.text-red-1 { - color: $red-1; -} - -// orange -.text-orange-8 { - color: $orange-8; -} -.text-orange-7 { - color: $orange-7; -} -.text-orange-6 { - color: $orange-6; -} -.text-orange-5 { - color: $orange-5; -} -.text-orange-4 { - color: $orange-4; -} -.text-orange-3 { - color: $orange-3; -} -.text-orange-2 { - color: $orange-2; -} -.text-orange-1 { - color: $orange-1; -} - -// yellow -.text-yellow-8 { - color: $yellow-8; -} -.text-yellow-7 { - color: $yellow-7; -} -.text-yellow-6 { - color: $yellow-6; -} -.text-yellow-5 { - color: $yellow-5; -} -.text-yellow-4 { - color: $yellow-4; -} -.text-yellow-3 { - color: $yellow-3; -} -.text-yellow-2 { - color: $yellow-2; -} -.text-yellow-1 { - color: $yellow-1; -} - -// green -.text-green-8 { - color: $green-8; -} -.text-green-7 { - color: $green-7; -} -.text-green-6 { - color: $green-6; -} -.text-green-5 { - color: $green-5; -} -.text-green-4 { - color: $green-4; -} -.text-green-3 { - color: $green-3; -} -.text-green-2 { - color: $green-2; -} -.text-green-1 { - color: $green-1; -} - -// cyan -.text-cyan-8 { - color: $cyan-8; -} -.text-cyan-7 { - color: $cyan-7; -} -.text-cyan-6 { - color: $cyan-6; -} -.text-cyan-5 { - color: $cyan-5; -} -.text-cyan-4 { - color: $cyan-4; -} -.text-cyan-3 { - color: $cyan-3; -} -.text-cyan-2 { - color: $cyan-2; -} -.text-cyan-1 { - color: $cyan-1; -} - -// purple -.text-purple-8 { - color: $purple-8; -} -.text-purple-7 { - color: $purple-7; -} -.text-purple-6 { - color: $purple-6; -} -.text-purple-5 { - color: $purple-5; -} -.text-purple-4 { - color: $purple-4; -} -.text-purple-3 { - color: $purple-3; -} -.text-purple-2 { - color: $purple-2; -} -.text-purple-1 { - color: $purple-1; -} - -$text-weights: ( - thin: 100, - light: 300, - regular: 400, - medium: 500, - bold: 700, - bolder: 900, -) !default; - -@each $weight, $value in $text-weights { - .text-weight-#{$weight} { - font-weight: $value; - } -} diff --git a/web/packages/tca-layout/src/common/style/font.scss b/web/packages/tca-layout/src/common/style/font.scss deleted file mode 100644 index 3ac5e75fd..000000000 --- a/web/packages/tca-layout/src/common/style/font.scss +++ /dev/null @@ -1,27 +0,0 @@ -.fs-12 { - font-size: 12px; -} - -.fs-14 { - font-size: 14px; -} - -.fs-16 { - font-size: 16px; -} - -.fs-18 { - font-size: 18px; -} - -.fs-20 { - font-size: 20px; -} - -.fs-24 { - font-size: 24px; -} - -.fs-28 { - font-size: 28px; -} diff --git a/web/packages/tca-layout/src/common/style/index.scss b/web/packages/tca-layout/src/common/style/index.scss deleted file mode 100644 index 0f70465eb..000000000 --- a/web/packages/tca-layout/src/common/style/index.scss +++ /dev/null @@ -1,53 +0,0 @@ -$font-family: "PingFang SC", "Helvetica Neue", "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei", "微软雅黑", sans-serif; -$font-size-base: 14px; -$line-height-base: 1.5; - -:global { - // 全局非模块化 CSS 在这里添加 - @import "./common"; - @import "./uikit.scss"; - - *, - *::before, - *::after { - box-sizing: border-box; - } - - body { - font-family: $font-family; - font-size: $font-size-base; - line-height: $line-height-base; - background: getColor(white, normal); - color: $text-color; - -webkit-font-smoothing: antialiased; - margin: 0; - } - - #container { - position: relative; - padding-top: 48px; - min-width: 1080px; - height: 100vh; - } - - .layout-uncompleted #container { - display: none; - } - - .menu-layout-expanded #container { - margin-left: 220px; - } - - .mini-menu-layout-expanded #container { - margin-left: 56px; - } - - .a-no-style, - .a-no-style:link, - .a-no-style:visited, - .a-no-style:hover, - .a-no-style:active { - text-decoration: none !important; - color: inherit !important; - } -} diff --git a/web/packages/tca-layout/src/common/style/reset.scss b/web/packages/tca-layout/src/common/style/reset.scss deleted file mode 100644 index dd98cbcaa..000000000 --- a/web/packages/tca-layout/src/common/style/reset.scss +++ /dev/null @@ -1,46 +0,0 @@ -body, -div, -dl, -dt, -dd, -ul, -ol, -li, -h1, -h2, -h3, -h4, -h5, -h6, -pre, -code, -form, -fieldset, -legend, -input, -textarea, -p, -blockquote, -th, -td, -hr, -button, -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - margin: 0; - padding: 0; -} - -ul, -ol { - list-style: none; -} diff --git a/web/packages/tca-layout/src/common/style/uikit.scss b/web/packages/tca-layout/src/common/style/uikit.scss deleted file mode 100644 index 5f6e28515..000000000 --- a/web/packages/tca-layout/src/common/style/uikit.scss +++ /dev/null @@ -1,87 +0,0 @@ -@import "./color.scss"; - -:global(.ant-tabs-nav) { - margin-bottom: 0 !important; - - &::before { - border-bottom-color: $grey-3 !important; - } -} - -:global(.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) { - font-weight: 600; - color: $grey-8; -} - -:global(.ant-tabs-tab) { - padding: 10px; - margin-right: 24px; - font-size: 16px; - transition: all 0.3s; - - &:hover { - color: $grey-8; - font-weight: 600; - } -} - -:global(.ant-tabs-tab-btn) { - &:active, - &:focus { - color: $grey-8; - font-weight: 600; - } -} - -:global(.ant-avatar) { - background: $grey-5; -} - -:global(.ant-table-wrapper) { - // 防止筛选项过长被挡住 - min-height: 300px; -} - -:global(.ant-table-tbody) { - & > tr { - td > a.link-name { - color: $grey-8; - } - - &:hover { - td > a.link-name { - color: $blue-5 !important; - } - } - } -} - -:global(.ant-tag) { - padding: 0px 8px; - border: none; - - &.warning { - color: $warging-color; - background-color: $warging-bg; - } - - &.success { - color: $success-color; - background-color: $success-bg; - } - - &.fatal { - color: $fatal-color; - background-color: $fatal-bg; - } - - &.error { - color: $error-color; - background-color: $error-bg; - } - - &.processing { - color: $tip-color; - background-color: $tip-bg; - } -} diff --git a/web/packages/tca-layout/src/component/container/index.tsx b/web/packages/tca-layout/src/component/container/index.tsx new file mode 100644 index 000000000..c08f8bde0 --- /dev/null +++ b/web/packages/tca-layout/src/component/container/index.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +interface ContainerProps { + children: any; +} + +const containerNode = document.getElementById('container'); + +/** 用于将内容放入container div内 */ +const Container = ({ children }: ContainerProps) => <> + {containerNode && ReactDOM.createPortal(children, containerNode)} +; + +export default Container; diff --git a/web/packages/tca-layout/src/components/global-breadcrumb/index.tsx b/web/packages/tca-layout/src/component/global-breadcrumb/index.tsx similarity index 89% rename from web/packages/tca-layout/src/components/global-breadcrumb/index.tsx rename to web/packages/tca-layout/src/component/global-breadcrumb/index.tsx index 0c61d99d7..1241f8977 100644 --- a/web/packages/tca-layout/src/components/global-breadcrumb/index.tsx +++ b/web/packages/tca-layout/src/component/global-breadcrumb/index.tsx @@ -1,9 +1,3 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React from 'react'; import { Breadcrumb } from 'coding-oa-uikit'; import { Link } from 'react-router-dom'; diff --git a/web/packages/tca-layout/src/components/global-breadcrumb/reducer.ts b/web/packages/tca-layout/src/component/global-breadcrumb/reducer.ts similarity index 55% rename from web/packages/tca-layout/src/components/global-breadcrumb/reducer.ts rename to web/packages/tca-layout/src/component/global-breadcrumb/reducer.ts index 1e0e9e53b..4093fce97 100644 --- a/web/packages/tca-layout/src/components/global-breadcrumb/reducer.ts +++ b/web/packages/tca-layout/src/component/global-breadcrumb/reducer.ts @@ -1,16 +1,10 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import { BreadcrumbActions, GbcState, EMPTY_BREADCRUMB, UPDATE_BREADCRUMB_DATA } from './types'; const initialState: GbcState = { data: [], }; -export default function gbcReducer(state = initialState, action: BreadcrumbActions) { +const breadcrumbReducer = (state = initialState, action: BreadcrumbActions) => { switch (action.type) { case UPDATE_BREADCRUMB_DATA: { return { @@ -24,4 +18,6 @@ export default function gbcReducer(state = initialState, action: BreadcrumbActio default: return state; } -} +}; + +export default breadcrumbReducer; diff --git a/web/packages/tca-layout/src/components/global-breadcrumb/style.scss b/web/packages/tca-layout/src/component/global-breadcrumb/style.scss similarity index 61% rename from web/packages/tca-layout/src/components/global-breadcrumb/style.scss rename to web/packages/tca-layout/src/component/global-breadcrumb/style.scss index 0238a0cb1..84babd028 100644 --- a/web/packages/tca-layout/src/components/global-breadcrumb/style.scss +++ b/web/packages/tca-layout/src/component/global-breadcrumb/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; .breadcrumb { margin-left: 10px; .arrow { diff --git a/web/packages/tca-layout/src/components/global-breadcrumb/types.ts b/web/packages/tca-layout/src/component/global-breadcrumb/types.ts similarity index 82% rename from web/packages/tca-layout/src/components/global-breadcrumb/types.ts rename to web/packages/tca-layout/src/component/global-breadcrumb/types.ts index 5727bdbc6..40da0267b 100644 --- a/web/packages/tca-layout/src/components/global-breadcrumb/types.ts +++ b/web/packages/tca-layout/src/component/global-breadcrumb/types.ts @@ -1,11 +1,3 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React from 'react'; - export enum ItemTypes { Text = 'text', Dropdown = 'dropdown', diff --git a/web/packages/tca-layout/src/component/layout-header/index.tsx b/web/packages/tca-layout/src/component/layout-header/index.tsx new file mode 100644 index 000000000..038ca3ae2 --- /dev/null +++ b/web/packages/tca-layout/src/component/layout-header/index.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import classnames from 'classnames'; +import { Space } from 'coding-oa-uikit'; + +// 模块内 +import LogoIco from '@src/images/favicon.ico'; +import s from './style.scss'; + + +interface HeaderProps { + leftContent?: React.ReactNode; + rightContent?: React.ReactNode; +} + +const Header = ({ leftContent, rightContent }: HeaderProps) => ( +
+ + + + + 腾讯云代码分析 + + + {leftContent} + + + {rightContent} + +
+); + +export default Header; diff --git a/web/packages/tca-layout/src/component/layout-header/style.scss b/web/packages/tca-layout/src/component/layout-header/style.scss new file mode 100644 index 000000000..3278b029d --- /dev/null +++ b/web/packages/tca-layout/src/component/layout-header/style.scss @@ -0,0 +1,23 @@ +@import "@tencent/micro-frontend-shared/style/color.scss"; + +$zindex-navbar: 1000 !default; +$height: 48px; + +.layout-header { + position: fixed; + top: 0; + left: 0; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0; + width: 100%; + height: $height; + box-shadow: 0 1px $grey-3; + background: $white; + z-index: $zindex-navbar; + + .left-content { + margin-left: 20px; + } +} \ No newline at end of file diff --git a/web/packages/tca-layout/src/components/menu-layout/index.tsx b/web/packages/tca-layout/src/component/layout-menu/index.tsx similarity index 85% rename from web/packages/tca-layout/src/components/menu-layout/index.tsx rename to web/packages/tca-layout/src/component/layout-menu/index.tsx index d448ac7ca..f103c111f 100644 --- a/web/packages/tca-layout/src/components/menu-layout/index.tsx +++ b/web/packages/tca-layout/src/component/layout-menu/index.tsx @@ -1,9 +1,3 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React, { ReactNode } from 'react'; import { Link } from 'react-router-dom'; import classnames from 'classnames'; @@ -21,45 +15,54 @@ const MenuLayoutExpanded = 'menu-layout-expanded'; const MiniMenuLayoutExpanded = 'mini-menu-layout-expanded'; export interface MenuItem { + /** 菜单名称 */ title: string; + /** 菜单图标 */ icon?: ReactNode; + /** 菜单链接 */ link?: string; - open?: boolean; // 跳转 + /** 是否跳转打开链接 */ + open?: boolean; + /** key */ key: string; + /** 子菜单 */ childrens?: MenuItem[]; + /** 是否折叠,存在子菜单才生效,默认不折叠 */ + isFold?: boolean; + /** 正则路由 */ regexMatch?: RegExp; + /** 是否存在分割线 */ divider?: boolean; } -interface IProps { - menus: MenuItem[]; +interface LayoutMenuProps { + /** 菜单项 */ + menus: MenuItem[], + /** breakpoint */ breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; + /** 菜单标题 */ title?: ReactNode; + /** 是否菜单title下展示border */ showTitleBottomBorder?: boolean; } -interface IState { +interface LayoutMenuState { collapsed: boolean; } -class MenuLayout extends React.Component { +class LayoutMenu extends React.Component { public state = { collapsed: false, }; - // eslint-disable-next-line @typescript-eslint/no-useless-constructor - constructor(props: IProps) { - super(props); - } - public componentDidMount() { this.onCollapse(this.state.collapsed); } /** - * 菜单折叠时增加class用于控制container显示内容 - * @param collapsed 折叠 - */ + * 菜单折叠时增加class用于控制container显示内容 + * @param collapsed 折叠 + */ public onCollapse(collapsed: boolean) { this.setState( { @@ -85,9 +88,9 @@ class MenuLayout extends React.Component { } /** - * 聚合菜单项 - * @param menus 菜单项 - */ + * 聚合菜单项 + * @param menus 菜单项 + */ public getMenuItems(menus: MenuItem[]) { const items: Array = []; menus.forEach((menus) => { @@ -101,10 +104,10 @@ class MenuLayout extends React.Component { } /** - * 根据路由获取选中菜单 - * @param menus 菜单 - * @return key - */ + * 根据路由获取选中菜单 + * @param menus 菜单 + * @return key + */ public getSelectedKey(menus: MenuItem[]) { const newMenus = this.getMenuItems(menus); const menuFilters = newMenus.filter((menu) => { @@ -122,11 +125,13 @@ class MenuLayout extends React.Component { } /** - * 默认获取所有sub菜单key - * @param menus 菜单项 - */ + * 默认获取所有sub菜单key + * @param menus 菜单项 + */ public getDefaultOpenKeys(menus: MenuItem[]) { - const menuFilters = menus.filter(menu => menu.childrens); + const selectedKey = this.getSelectedKey(menus); + const menuFilters = menus.filter(menu => menu.childrens + && (!menu.isFold || menu.childrens.filter(({ key }) => key === selectedKey).length > 0)); return menuFilters.map(menu => menu.key); } @@ -260,4 +265,4 @@ class MenuLayout extends React.Component { } } -export default MenuLayout; +export default LayoutMenu; diff --git a/web/packages/tca-layout/src/components/menu-layout/open-link.svg b/web/packages/tca-layout/src/component/layout-menu/open-link.svg similarity index 100% rename from web/packages/tca-layout/src/components/menu-layout/open-link.svg rename to web/packages/tca-layout/src/component/layout-menu/open-link.svg diff --git a/web/packages/tca-layout/src/components/menu-layout/style.scss b/web/packages/tca-layout/src/component/layout-menu/style.scss similarity index 98% rename from web/packages/tca-layout/src/components/menu-layout/style.scss rename to web/packages/tca-layout/src/component/layout-menu/style.scss index 2c962189f..ce2fdc6f2 100644 --- a/web/packages/tca-layout/src/components/menu-layout/style.scss +++ b/web/packages/tca-layout/src/component/layout-menu/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; $zindex-navbar: 1000 !default; $menu-full-size-width: 220px; $menu-full-size-background-color: #f7f8fa; diff --git a/web/packages/tca-layout/src/components/copy/index.tsx b/web/packages/tca-layout/src/components/copy/index.tsx deleted file mode 100644 index 58d3aaaee..000000000 --- a/web/packages/tca-layout/src/components/copy/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/** - * 复制到剪切板 - */ - -import React from 'react'; -import cn from 'classnames'; -import CopyToClipboard from 'react-copy-to-clipboard'; -import { Tooltip, message } from 'coding-oa-uikit'; -import CopyIcon from 'coding-oa-uikit/lib/icon/Copy'; - -import copyStyle from './style.scss'; - -interface CopyProps { - text: string; // tooltip 提示文字 - copyText?: string; // copy 文字,不传默认为 text - msg?: string; // 复制成功提示,不传默认为 “复制成功” - className?: any; - style?: any; - getPopupContainer?: any -} - -const Copy = (props: CopyProps) => { - const { text, copyText, msg, className, style, getPopupContainer } = props; - - return ( - - message.success(msg || '复制成功')} - > - {/* tooltip 组件会默认替换第一个子节点类名 */} - - - - - - ); -}; - -export default Copy; diff --git a/web/packages/tca-layout/src/components/copy/style.scss b/web/packages/tca-layout/src/components/copy/style.scss deleted file mode 100644 index 735a49d36..000000000 --- a/web/packages/tca-layout/src/components/copy/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '@src/common/style/color.scss'; - -.copy-icon { - color: $grey-6; - margin-left: 6px; - transition: color 0.3s; - cursor: pointer; - - &:hover { - color: $grey-8; - } - -} \ No newline at end of file diff --git a/web/packages/tca-layout/src/components/ellipsis/index.tsx b/web/packages/tca-layout/src/components/ellipsis/index.tsx deleted file mode 100644 index 43042ace1..000000000 --- a/web/packages/tca-layout/src/components/ellipsis/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; - -interface IProps { - maxWidth?: number; - className?: string; - children?: React.ReactNode; -} - -const EllipsisTemplate = ({ maxWidth, className, children }: IProps) => ( -
- {children} -
-); - -export default EllipsisTemplate; diff --git a/web/packages/tca-layout/src/components/filter/FilterItem.tsx b/web/packages/tca-layout/src/components/filter/FilterItem.tsx deleted file mode 100644 index 89f5e6df2..000000000 --- a/web/packages/tca-layout/src/components/filter/FilterItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React from 'react'; -import cn from 'classnames'; -import { Form } from 'coding-oa-uikit'; - -interface ItemProps { - children: React.ReactNode; - label?: string; - className?: any; -} - -const Item = (props: ItemProps & any) => { - const { children, label, className, ...otherProps } = props; - return ( - - {children} - - ); -}; - -export default Item; diff --git a/web/packages/tca-layout/src/components/filter/index.tsx b/web/packages/tca-layout/src/components/filter/index.tsx deleted file mode 100644 index 7e5ac0396..000000000 --- a/web/packages/tca-layout/src/components/filter/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/** - * 过滤筛选组件 - */ - -import React from 'react'; -import { Form } from 'coding-oa-uikit'; - -import Item from './FilterItem'; - -interface FilterProps { - children: React.ReactNode -} - -const Filter = (props: FilterProps & any) => { - const { children, ...otherProps } = props; - return ( -
- {children} -
- ); -}; - -Filter.Item = Item; - -export default Filter; diff --git a/web/packages/tca-layout/src/components/loading/index.tsx b/web/packages/tca-layout/src/components/loading/index.tsx deleted file mode 100644 index a62ea1498..000000000 --- a/web/packages/tca-layout/src/components/loading/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/** - * 加载中组件 - */ - -import React from 'react'; -import LoadingIcon from 'coding-oa-uikit/lib/icon/Loading'; - -import style from './style.scss'; - -const Loading = () => ( -
- - 加载中 -
-); - -export default Loading; diff --git a/web/packages/tca-layout/src/components/loading/style.scss b/web/packages/tca-layout/src/components/loading/style.scss deleted file mode 100644 index ea76433af..000000000 --- a/web/packages/tca-layout/src/components/loading/style.scss +++ /dev/null @@ -1,11 +0,0 @@ -.loading { - display: flex; - align-items: center; - justify-content: center; - padding: 20px 0; - - .icon { - margin-right: 8px; - font-size: 16px; - } -} diff --git a/web/packages/tca-layout/src/components/modal/danger-modal.tsx b/web/packages/tca-layout/src/components/modal/danger-modal.tsx deleted file mode 100644 index 220da53cf..000000000 --- a/web/packages/tca-layout/src/components/modal/danger-modal.tsx +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React, { ReactNode } from 'react'; -import { Modal, Button } from 'coding-oa-uikit'; -// 项目内 -import { t } from '@src/i18n/i18next'; - -interface IProps { - title: string; - visible: boolean; - onCancel: (e: React.MouseEvent) => void; - onOk: (e: React.MouseEvent) => void; - content?: ReactNode; - okText?: string ; -} - -const DangerModal = (props: IProps) => { - const { visible, title, onCancel, onOk, content, okText = t('确认删除') } = props; - - return ( - - {okText} - , - , - ]} - > - {content} - - ); -}; - -export default DangerModal; diff --git a/web/packages/tca-layout/src/components/notification/index.tsx b/web/packages/tca-layout/src/components/notification/index.tsx deleted file mode 100644 index 9fc04d10b..000000000 --- a/web/packages/tca-layout/src/components/notification/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as useNotification } from './useNotification'; diff --git a/web/packages/tca-layout/src/components/notification/useNotification.tsx b/web/packages/tca-layout/src/components/notification/useNotification.tsx deleted file mode 100644 index 1454b30ff..000000000 --- a/web/packages/tca-layout/src/components/notification/useNotification.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { useEffect } from 'react'; -import Moment from 'moment'; -import { notification, Button, Space } from 'coding-oa-uikit'; -import { ArgsProps } from 'coding-oa-uikit/lib/notification'; - -/** 通知存储数据结构 */ -interface NotifyStorageData { - /** 不再提醒 */ - neverRemind: boolean; - /** 过期时间 */ - expireTimestamp?: number; -} - -/** 获取在LocalStorage的通知数据 */ -const getNotificationDataByLocalStorage = (key: string) => { - const keyValue = localStorage.getItem(key); - if (keyValue) { - try { - const keyObj: NotifyStorageData = JSON.parse(keyValue); - return keyObj; - } catch (error) { - // 解析失败 - } - } - return null; -}; - -/** 设置通知数据到LocalStorage */ -const setNotificationDataToLocalStorage = (key: string, notifyStorageData: NotifyStorageData) => { - localStorage.setItem(key, JSON.stringify(notifyStorageData)); -}; - -/** 通知入参数数据结构 */ -interface NotificationProps { - /** 唯一标识 */ - key: string, - /** 通知类型 */ - type: 'info' | 'success' | 'error' | 'warning', - /** 是否开启过期操作 */ - useExpireOper?: boolean; - /** 通知其他参数 */ - notifyArgs: Omit -} - -/** 通知hooks */ -const useNotification = ({ key, type, useExpireOper = false, notifyArgs }: NotificationProps) => { - const { btn, ...rest } = notifyArgs; - - useEffect(() => { - if (useExpireOper) { - const notifyStorageData = getNotificationDataByLocalStorage(key); - if (notifyStorageData?.neverRemind - || (notifyStorageData?.expireTimestamp && Moment().valueOf() < notifyStorageData.expireTimestamp) - ) { - return; - } - } - - notification[type]({ - duration: null, - btn: useExpireOper ? - - - : btn, - ...rest, - key, - }); - }, []); -}; - -export default useNotification; diff --git a/web/packages/tca-layout/src/components/tips/index.tsx b/web/packages/tca-layout/src/components/tips/index.tsx deleted file mode 100644 index f2c28df4b..000000000 --- a/web/packages/tca-layout/src/components/tips/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/** - * 提示组件 - */ - -import React from 'react'; -import cn from 'classnames'; -import { Tooltip } from 'coding-oa-uikit'; -import QuestionCircle from 'coding-oa-uikit/lib/icon/QuestionCircle'; - -import style from './style.scss'; - -interface TipsProps { - title: string | React.ReactNode; - className?: any; - icon?: React.ReactNode -} - -const Tips = (props: TipsProps) => { - const { title, className, icon, ...otherProps } = props; - - return ( - - - { - icon ? ( - icon - ) : ( - - ) - } - - - ); -}; - -export default Tips; diff --git a/web/packages/tca-layout/src/components/tips/style.scss b/web/packages/tca-layout/src/components/tips/style.scss deleted file mode 100644 index 1acefadd1..000000000 --- a/web/packages/tca-layout/src/components/tips/style.scss +++ /dev/null @@ -1,12 +0,0 @@ -@import "@src/common/style/color.scss"; - -.question-icon { - color: $grey-6; - margin-left: 6px; - transition: color 0.3s; - cursor: pointer; - - &:hover { - color: $grey-8; - } -} diff --git a/web/packages/tca-layout/src/constant/auth.ts b/web/packages/tca-layout/src/constant/auth.ts new file mode 100644 index 000000000..1c0c32586 --- /dev/null +++ b/web/packages/tca-layout/src/constant/auth.ts @@ -0,0 +1,105 @@ +import { generateOptions } from '@tencent/micro-frontend-shared/util'; + +export enum AuthTypeEnum { + HTTP = 'password', + SSH = 'ssh_token', + OAUTH = 'oauth', +} + +export enum AuthTypeTxtEnum { + HTTP = '用户名 + 密码', + SSH = 'SSH', + OAUTH = 'OAuth', +} + +/** 凭证映射,对应 api 返回的字段名*/ +export const SCM_MAP = { + [AuthTypeEnum.HTTP]: 'scm_account', + [AuthTypeEnum.SSH]: 'scm_ssh', + [AuthTypeEnum.OAUTH]: 'scm_oauth', +}; + +export const AUTH_TYPE_CHOICES = { + [AuthTypeEnum.HTTP]: AuthTypeTxtEnum.HTTP, + [AuthTypeEnum.SSH]: AuthTypeTxtEnum.SSH, + [AuthTypeEnum.OAUTH]: AuthTypeTxtEnum.OAUTH, +}; + +export const AUTH_TYPE_OPTIONS = [{ + label: AUTH_TYPE_CHOICES[AuthTypeEnum.HTTP], + value: AuthTypeEnum.HTTP, +}, { + label: AUTH_TYPE_CHOICES[AuthTypeEnum.SSH], + value: AuthTypeEnum.SSH, +}]; + +/** OAuth平台类型名称 */ +export enum ScmPlatformNameEnum { + TGIT = 'tgit', + GIT_TENCENT = 'tgitsaas', + CODING = 'coding', + GITHUB = 'github', + GITEE = 'gitee', + GITLAB = 'gitlab', +} + +export enum ScmPlatformEnum { + TGIT = 1, + GIT_TENCENT, + CODING, + GITHUB, + GITEE, + GITLAB, + OTHER, +} + +export const SCM_PLATFORM_CHOICES = { + [ScmPlatformEnum.TGIT]: '腾讯工蜂(OA)', + [ScmPlatformEnum.GIT_TENCENT]: '腾讯工蜂', + [ScmPlatformEnum.CODING]: 'Coding', + [ScmPlatformEnum.GITHUB]: 'GitHub', + [ScmPlatformEnum.GITEE]: 'Gitee', + [ScmPlatformEnum.GITLAB]: 'GitLab', + [ScmPlatformEnum.OTHER]: '其它平台', +}; + +export const SCM_PLATFORM_OPTIONS = generateOptions(SCM_PLATFORM_CHOICES, true); + +export const DEFAULT_SCM_PLATFORM = [ + { + id: ScmPlatformEnum.TGIT, + scm_platform: ScmPlatformEnum.TGIT, + scm_platform_name: ScmPlatformNameEnum.TGIT, + }, + { + id: ScmPlatformEnum.GIT_TENCENT, + scm_platform: ScmPlatformEnum.GIT_TENCENT, + scm_platform_name: ScmPlatformNameEnum.GIT_TENCENT, + }, + { + id: ScmPlatformEnum.CODING, + scm_platform: ScmPlatformEnum.CODING, + scm_platform_name: ScmPlatformNameEnum.CODING, + }, + { + id: ScmPlatformEnum.GITHUB, + scm_platform: ScmPlatformEnum.GITHUB, + scm_platform_name: ScmPlatformNameEnum.GITHUB, + }, + { + id: ScmPlatformEnum.GITEE, + scm_platform: ScmPlatformEnum.GITEE, + scm_platform_name: ScmPlatformNameEnum.GITEE, + }, + { + id: ScmPlatformEnum.GITLAB, + scm_platform: ScmPlatformEnum.GITLAB, + scm_platform_name: ScmPlatformNameEnum.GITLAB, + }, +]; + +export enum LevelEnum { + NORMAL = 1, + VIP, + SUPER_VIP, +} diff --git a/web/packages/tca-layout/src/constant/index.ts b/web/packages/tca-layout/src/constant/index.ts new file mode 100644 index 000000000..29e3613a2 --- /dev/null +++ b/web/packages/tca-layout/src/constant/index.ts @@ -0,0 +1,31 @@ +import { generateOptions } from '@tencent/micro-frontend-shared/util'; +export * from './org'; +export * from './auth'; +export * from './tool'; +export * from './toollib'; +export * from './node'; + +export const DEFAULT_PAGER = { + count: 0, + pageSize: 10, + pageStart: 0, +}; + +export const DEFAULT_TEAM_PAGER = { + count: 0, + pageSize: 12, + pageStart: 0, + allLoaded: true, +}; + +export enum RepoTypeEnum { + GIT = 'git', + SVN = 'svn' +} + +export const REPO_TYPE_CHOICES = { + [RepoTypeEnum.GIT]: 'GIT', + [RepoTypeEnum.SVN]: 'SVN', +}; + +export const REPO_TYPE_OPTIONS = generateOptions(REPO_TYPE_CHOICES); diff --git a/web/packages/tca-layout/src/constant/node.ts b/web/packages/tca-layout/src/constant/node.ts new file mode 100644 index 000000000..95ccc7da5 --- /dev/null +++ b/web/packages/tca-layout/src/constant/node.ts @@ -0,0 +1,84 @@ +import { SearchFormField } from '@tencent/micro-frontend-shared/component/search'; +import { generateOptions } from '@tencent/micro-frontend-shared/util'; + +export const STATUS_ENUM = { + DISACTIVE: 0, + ACTIVE: 1, + OFFLINE: 2, +}; + +export const STATUS_CHOICES = { + [STATUS_ENUM.DISACTIVE]: '不可用', + [STATUS_ENUM.ACTIVE]: '活跃', + [STATUS_ENUM.OFFLINE]: '离线', +}; + +export const STATUS_OPTIONS = generateOptions(STATUS_CHOICES, true); + +export const STATE_ENUM = { + FREE: 0, + BUSY: 1, +}; + +export const STATE_CHOICES = { + [STATE_ENUM.BUSY]: '忙碌', + [STATE_ENUM.FREE]: '空闲', +}; + +export const TAG_TYPE_ENUM = { + PUBLIC: 1, + PRIVATE: 2, + DISABLED: 99, +}; + +export const TAG_TYPE_CHOICES = { + [TAG_TYPE_ENUM.PUBLIC]: '公共', + [TAG_TYPE_ENUM.PRIVATE]: '团队', + [TAG_TYPE_ENUM.DISABLED]: '停用', +}; + +export const TAG_TYPE_OPTIONS = generateOptions(TAG_TYPE_CHOICES, true); + +export const TAG_TYPE_COLOR = { + [TAG_TYPE_ENUM.PUBLIC]: 'geekblue', + [TAG_TYPE_ENUM.PRIVATE]: 'blue', + [TAG_TYPE_ENUM.DISABLED]: 'default', +}; + +export const TASK_STATE_ENUM = { + WAITING: 0, + RUNNING: 1, + CLOSED: 2, + CLOSING: 3, + INITING: 4, + INITED: 5, +}; + +export const TASK_STATE_CHOICES = { + [TASK_STATE_ENUM.WAITING]: '等待中', + [TASK_STATE_ENUM.RUNNING]: '执行中', + [TASK_STATE_ENUM.CLOSED]: '已结束', + [TASK_STATE_ENUM.CLOSING]: '入库中', + [TASK_STATE_ENUM.INITING]: '初始化', + [TASK_STATE_ENUM.INITED]: '已初始化', +}; + +export const getNodeSearchFields = (tagOptions: any[]): SearchFormField[] => [{ + name: 'name', + type: 'string', + formType: 'input', + placeholder: '节点名称', +}, { + name: 'manager', + label: '负责人', + type: 'string', + formType: 'input', + placeholder: '负责人', +}, { + name: 'exec_tags', + label: '所属标签', + type: 'string', + formType: 'select', + placeholder: '全部', + options: tagOptions, +}]; diff --git a/web/packages/tca-layout/src/constant/org.ts b/web/packages/tca-layout/src/constant/org.ts new file mode 100644 index 000000000..2e6930827 --- /dev/null +++ b/web/packages/tca-layout/src/constant/org.ts @@ -0,0 +1,47 @@ +export enum OrgStatusEnum { + ACTIVE = 1, + DISACTIVE, +} + +export const ORG_STATUS_CHOICES = { + [OrgStatusEnum.ACTIVE]: '已激活', + [OrgStatusEnum.DISACTIVE]: '审核中', +}; + +export enum OrgApplyStatusEnum { + CHECKING = 1, + CHECKED, + CANCELED, +} + +export const ORG_APPLY_STATUS_CHOICES = { + [OrgApplyStatusEnum.CHECKING]: '审核中', + [OrgApplyStatusEnum.CHECKED]: '审核完成', + [OrgApplyStatusEnum.CANCELED]: '取消申请', +}; + +export enum OrgCheckResultEnum { + PASS = 1, + NO_PASS, +} + +export const ORG_CHECK_RESULT_CHOICES = { + [OrgCheckResultEnum.PASS]: '审核通过', + [OrgCheckResultEnum.NO_PASS]: '审核不通过', +}; + +export enum OrgMemberRoleEnum { + ADMIN = 1, + USER, +} + +export const ORG_MEMBER_ROLE_INFO = { + [OrgMemberRoleEnum.ADMIN]: { + tit: '管理员', + desc: '(具备团队内全部权限,请谨慎赋予管理员权限)', + }, + [OrgMemberRoleEnum.USER]: { + tit: '普通成员', + desc: '(具备团队内部分查看、创建项目等相关权限)', + }, +}; diff --git a/web/packages/tca-layout/src/constant/tool.ts b/web/packages/tca-layout/src/constant/tool.ts new file mode 100644 index 000000000..87c47b75b --- /dev/null +++ b/web/packages/tca-layout/src/constant/tool.ts @@ -0,0 +1,67 @@ +import invert from 'lodash/invert'; +import { generateOptions } from '@tencent/micro-frontend-shared/util'; + +export enum ToolStatusEnum { + NORMAL, + SUSPENSION, + DOWN, + EXPERIENCE +} + +export const TOOL_STATUS_CHOICES = { + [ToolStatusEnum.NORMAL]: '正常使用', + [ToolStatusEnum.SUSPENSION]: '暂停使用', + [ToolStatusEnum.DOWN]: '已下架', + [ToolStatusEnum.EXPERIENCE]: '体验运营', +}; + +export const TOOL_STATUS_OPTIONS = generateOptions(TOOL_STATUS_CHOICES, true); + +export enum ToolScopeEnum { + PUBLIC, + PRIVATE, + MAINTAIN, + CUSTOM +} + +export enum RuleSeverityEnum { + FATAL = 1, + ERROR, + WARNING, + INFO, +} + +export const RuleSeverityInvertEnum = invert(RuleSeverityEnum); + +export const RULE_SEVERITY_CHOICES = { + [RuleSeverityEnum.FATAL]: '致命', + [RuleSeverityEnum.ERROR]: '错误', + [RuleSeverityEnum.WARNING]: '警告', + [RuleSeverityEnum.INFO]: '提示', +}; + +export const RULE_SEVERITY_OPTIONS = generateOptions(RULE_SEVERITY_CHOICES, true); + +export enum RuleCategoryEnum { + CORRECTNESS = 1, + SECURITY, + PERFORMANCE, + USABILITY, + ACCESSIBILITY, + I18N, + CONVENTION, + OTHER, +} + +export const RULE_CATEGORY_CHOICES = { + [RuleCategoryEnum.CORRECTNESS]: '功能', + [RuleCategoryEnum.SECURITY]: '安全', + [RuleCategoryEnum.PERFORMANCE]: '性能', + [RuleCategoryEnum.USABILITY]: '可用性', + [RuleCategoryEnum.ACCESSIBILITY]: '无障碍化', + [RuleCategoryEnum.I18N]: '国际化', + [RuleCategoryEnum.CONVENTION]: '风格', + [RuleCategoryEnum.OTHER]: '其他', +}; + +export const RULE_CATEGORY_OPTIONS = generateOptions(RULE_CATEGORY_CHOICES, true); diff --git a/web/packages/tca-layout/src/constant/toollib.ts b/web/packages/tca-layout/src/constant/toollib.ts new file mode 100644 index 000000000..892ea77ee --- /dev/null +++ b/web/packages/tca-layout/src/constant/toollib.ts @@ -0,0 +1,27 @@ +import { generateOptions } from '@tencent/micro-frontend-shared/util'; + +export enum LibTypeEnum { + PRIVATE = 'private', + PUBLIC = 'public' +} + +export const LIB_TYPE: any = { + [LibTypeEnum.PRIVATE]: '私有依赖', + [LibTypeEnum.PUBLIC]: '公共依赖', +}; + +enum LibEnvEnum { + LINUX = 'linux', + MAC = 'mac', + WINDOWS = 'windows', + ARM64_LINUX = 'linux_arm64' +} + +export const LIB_ENV = { + [LibEnvEnum.LINUX]: 'Linux', + [LibEnvEnum.MAC]: 'Mac', + [LibEnvEnum.WINDOWS]: 'Windows', + [LibEnvEnum.ARM64_LINUX]: 'Linux ARM64', +}; + +export const LIB_ENV_OPTIONS = generateOptions(LIB_ENV, false); diff --git a/web/packages/tca-layout/src/constants.ts b/web/packages/tca-layout/src/constants.ts deleted file mode 100644 index 9d16be0c1..000000000 --- a/web/packages/tca-layout/src/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -export default { -}; diff --git a/web/packages/tca-layout/src/constants/org.ts b/web/packages/tca-layout/src/constants/org.ts deleted file mode 100644 index 7627e0149..000000000 --- a/web/packages/tca-layout/src/constants/org.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import { t } from '@src/i18n/i18next'; - -export const STATUS_ENUM = { - ACTIVE: 1, - DISACTIVE: 2, -}; - -export const STATUS_CHOICES = { - [STATUS_ENUM.ACTIVE]: t('已激活'), - [STATUS_ENUM.DISACTIVE]: t('审核中'), -}; - -export const APPLY_STATUS_ENUM = { - CHECKING: 1, - CHECKED: 2, - CANCELED: 3, -}; - -export const APPLY_STATUS_CHOICES = { - [APPLY_STATUS_ENUM.CHECKING]: t('审核中'), - [APPLY_STATUS_ENUM.CHECKED]: t('审核完成'), - [APPLY_STATUS_ENUM.CANCELED]: t('取消申请'), -}; - -export const CHECK_RESULT_ENUM = { - PASS: 1, - NO_PASS: 2, -}; - -export const CHECK_RESULT_CHOICES = { - [CHECK_RESULT_ENUM.PASS]: t('审核通过'), - [CHECK_RESULT_ENUM.NO_PASS]: t('审核不通过'), -}; diff --git a/web/packages/tca-layout/src/context/constant.ts b/web/packages/tca-layout/src/context/constant.ts deleted file mode 100644 index 522ed6c79..000000000 --- a/web/packages/tca-layout/src/context/constant.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -export const SET_USERINFO = 'SET_USERINFO'; diff --git a/web/packages/tca-layout/src/context/store.tsx b/web/packages/tca-layout/src/context/store.tsx deleted file mode 100644 index 1d612903d..000000000 --- a/web/packages/tca-layout/src/context/store.tsx +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React, { createContext, useReducer, useContext } from 'react'; -import * as Constant from './constant'; -import { noop } from 'lodash'; - -interface StateProps { - userinfo: any; // 用户信息 -} - -interface ActionProps { - type: string; - payload: any; -} - -const initialState: StateProps = { - userinfo: {}, -}; - -const StateContext = createContext(initialState); -const DispatchContext = createContext(noop); - -const reducer = (state: StateProps, action: ActionProps) => { - switch (action.type) { - case Constant.SET_USERINFO: { - const userinfo = action.payload; - return { - ...state, - userinfo, - }; - } - default: { - return state; - } - } -}; - -const StoreProvider = ({ children }: { children: any }) => { - const [state, dispatch] = useReducer(reducer, initialState); - - return ( - - {children} - - ); -}; - -const useStateStore = () => useContext(StateContext); -const useDispatchStore = () => useContext(DispatchContext); - -export { StoreProvider, useStateStore, useDispatchStore }; diff --git a/web/packages/tca-layout/src/i18n/i18next.ts b/web/packages/tca-layout/src/i18n/i18next.ts deleted file mode 100644 index 14f029bc1..000000000 --- a/web/packages/tca-layout/src/i18n/i18next.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import i18next from 'i18next'; - -const t = i18next.t.bind(i18next); - -export { t }; - -export default i18next; diff --git a/web/packages/tca-layout/src/i18n/index.ts b/web/packages/tca-layout/src/i18n/index.ts deleted file mode 100644 index a74bce2d0..000000000 --- a/web/packages/tca-layout/src/i18n/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/* tslint:disable */ -// 请确保 i18n 初始化文件最先加载 -import i18next from 'i18next'; -import { initReactI18next } from 'react-i18next'; -import Cookie from 'universal-cookie'; - -const cookie = new Cookie(); -const language = cookie.get('language') || 'zh_CN'; - -let translation = {}; - -try { - // eslint-disable-next-line @typescript-eslint/no-require-imports - translation = require(`./locales/${language}/translation.json`); -} catch (e) { - translation = {}; -} - -const resources = { - zh_CN: { - translation, - }, - en_US: { - translation, - }, -}; - -i18next.use(initReactI18next).init({ - lng: 'zh_CN', - keySeparator: false, - nsSeparator: false, - interpolation: { - escapeValue: false, - }, - resources, -}); - -export const isEnglish = () => language === 'en_US'; - -export default i18next; diff --git a/web/packages/tca-layout/src/i18n/locales/en_US/translation.json b/web/packages/tca-layout/src/i18n/locales/en_US/translation.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/web/packages/tca-layout/src/i18n/locales/en_US/translation.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/web/packages/tca-layout/src/i18n/locales/zh_CN/translation.json b/web/packages/tca-layout/src/i18n/locales/zh_CN/translation.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/web/packages/tca-layout/src/i18n/locales/zh_CN/translation.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/web/packages/tca-layout/src/i18n/locales/zh_TW/translation.json b/web/packages/tca-layout/src/i18n/locales/zh_TW/translation.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/web/packages/tca-layout/src/i18n/locales/zh_TW/translation.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/web/packages/tca-layout/src/images/github.svg b/web/packages/tca-layout/src/images/github.svg new file mode 100644 index 000000000..b79d99a49 --- /dev/null +++ b/web/packages/tca-layout/src/images/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/packages/tca-layout/src/index.tsx b/web/packages/tca-layout/src/index.tsx index 5b5584e75..64f682969 100644 --- a/web/packages/tca-layout/src/index.tsx +++ b/web/packages/tca-layout/src/index.tsx @@ -1,82 +1,26 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import '@src/common/style/index.scss'; import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { Provider } from 'react-redux'; -import { createStore, combineReducers } from 'redux'; -import Cookie from 'universal-cookie'; -import { ConfigProvider } from 'coding-oa-uikit'; -import 'coding-oa-uikit/dist/coding-oa-uikit.css'; - -import { StoreProvider } from './context/store'; -import reducers, { injectGlobalReducer } from './reducer'; +import MicroInit from '@tencent/micro-frontend-shared/component/micro-init'; +import initI18next from '@tencent/micro-frontend-shared/i18n'; +import { initReactI18next } from 'react-i18next'; -import './i18n'; +// 项目内 +import './style.scss'; import Root from './root'; - +import stores from './store'; +import { State, Action } from './store/types'; +import reducers from './reducer'; import pkg from '../package.json'; -const ID = 'layout'; -const cookie = new Cookie(); -const language = cookie.get('language') || 'zh_CN'; - -let locale: any = ''; -try { - locale = require(`coding-oa-uikit/lib/locale/${language}.js`); -} catch (e) { - locale = require('coding-oa-uikit/lib/locale/zh_CN.js'); -} - -const create = (rootDom: HTMLElement) => { - const e = document.getElementById(ID); - if (rootDom && !e) { - const container = document.createElement('div'); - container.id = ID; - rootDom.appendChild(container); - } -}; - -function bootstrap() { console.log(''); } - -const mount = (props: any) => { - const { rootDom, injectAsyncReducer, store } = props; - create(rootDom); - injectAsyncReducer && injectGlobalReducer(injectAsyncReducer); - render( - - - (node ? node.parentNode : document.body)} - > - - - - , - document.getElementById(ID), - ); -}; - -const unmount = () => { - const e = document.getElementById(ID); - if (e) { - unmountComponentAtNode(e); - } -}; - -if (typeof window.microHook === 'object') { - window.microHook.registerApp(pkg.name, { - bootstrap, - mount, - unmount, - }); -} else { - const store = createStore(combineReducers({ ...reducers })); - mount({ store }); -} +// 初始化i18n +initI18next({ modules: [initReactI18next] }); + +MicroInit({ + id: 'layout', + name: pkg.name, + container: , + reducers, + hookStore: { + enable: true, + stores, + }, +}); diff --git a/web/packages/tca-layout/src/init-matomo.tsx b/web/packages/tca-layout/src/init-matomo.tsx new file mode 100644 index 000000000..cba3fd253 --- /dev/null +++ b/web/packages/tca-layout/src/init-matomo.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +import { useInitMamoto } from './utils/matomo'; + +interface InitMatomoProps { + children: React.ReactNode +} + +/** + * 初始化matomo + */ +const InitMatomo = ({ children }: InitMatomoProps) => { + useInitMamoto(); + return <>{children}; +}; + +export default InitMatomo; diff --git a/web/packages/tca-layout/src/load-init-service.tsx b/web/packages/tca-layout/src/load-init-service.tsx index 0bbbab7c2..989e9efda 100644 --- a/web/packages/tca-layout/src/load-init-service.tsx +++ b/web/packages/tca-layout/src/load-init-service.tsx @@ -1,76 +1,87 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React, { useState, useEffect, FC } from 'react'; import { useDispatch } from 'react-redux'; -import LoadingIcon from 'coding-oa-uikit/lib/icon/Loading'; +import { useDispatchStore } from '@tencent/micro-frontend-shared/hook-store'; +import { useFetch } from '@tencent/micro-frontend-shared/hooks'; +import { LogMgr } from '@tencent/micro-frontend-shared/util'; +import Loading from '@tencent/micro-frontend-shared/component/loading'; // 项目内 -import { t } from '@src/i18n/i18next'; -import { useDispatchStore } from '@src/context/store'; -import { SET_USERINFO } from '@src/context/constant'; import Constant from '@src/reducer/constant'; -import { gUserInfo } from '@src/services/user'; -import { setLayoutCompletedClass, info } from '@src/utils'; -import { useNotification } from '@src/components/notification' +import { UserAction, SET_USERINFO } from '@src/store/user'; +import { setPvUserInfo } from '@src/utils/matomo'; +import { getUserAvatarURL } from '@src/utils'; +import { UserAPI } from '@plat/api'; +import { initRequest } from '@plat/util'; +import { useNotification, useVersionChangeRedirect } from '@plat/hooks'; /** * 初始化页面时的一些请求 */ const LoadInitService: FC = ({ children }: any) => { const [loading, setLoading] = useState(true); - const dispatch = useDispatchStore(); + const dispatch = useDispatchStore(); const storeDispatch = useDispatch(); - useNotification({ - key: 'notify-license-trial', - type: 'info', - useExpireOper: true, - notifyArgs: { - message: '免费体验增强分析模块', - description: <> - TCA为开源社区免费提供更多功能精度更高的增强分析模块,欢迎免费申请License体验。详情请参考增强分析模块文档 - - } - }) + useNotification(); + useVersionChangeRedirect(); useEffect(() => { - storeDispatch({ - type: Constant.SET_LAYOUT_COMPLETED, - payload: false, - }); - // 获取用户信息,并存储到store中 - gUserInfo().then((res) => { + // 处理一些初始化时额外需要的请求 + initRequest?.(dispatch, storeDispatch); + }, []); + + useFetch(UserAPI.getUserInfo, [], { + onPreHandler: () => { + storeDispatch({ + type: Constant.SET_LAYOUT_COMPLETED, + payload: false, + }); + }, + onSuccess: (data) => { + const { avatar, avatar_url: avatarUrl } = data; + const url = avatar || avatarUrl || getUserAvatarURL(data); + const userinfo = { + ...data, + avatar: url, + avatar_url: url, + }; dispatch({ type: SET_USERINFO, - payload: res, + payload: userinfo, }); - setLoading(false); - // layout加载完毕 - info('loading finished'); storeDispatch({ type: Constant.SET_USERINFO, - payload: res - }) - storeDispatch({ - type: Constant.SET_LAYOUT_COMPLETED, - payload: true, + payload: userinfo, }); - }); - }, []); + setLoading(false); + // layout加载完毕 + LogMgr.info('loading finished'); + const timer = setTimeout(() => { + storeDispatch({ + type: Constant.SET_LAYOUT_COMPLETED, + payload: true, + }); + clearTimeout(timer); + }, 200); + setPvUserInfo(userinfo); + }, + }); - setLayoutCompletedClass(loading); + useEffect(() => { + // 根据loading状态设置layout加载class,用于控制container显示/隐藏 + const node = document.getElementById('main-container'); + const layoutUnCompletedClass = 'layout-uncompleted'; + if (node) { + if (loading && !node.classList.contains(layoutUnCompletedClass)) { + node.classList.add(layoutUnCompletedClass); + } else if (!loading && node.classList.contains(layoutUnCompletedClass)) { + node.classList.remove(layoutUnCompletedClass); + } + } + }, [loading]); if (loading) { - return ( -
- - {t('正在加载')}... -
- ); + return ; } return <>{children}; }; diff --git a/web/packages/tca-layout/src/modules/git-oauth/index.tsx b/web/packages/tca-layout/src/modules/git-oauth/index.tsx index 8c1a15ecb..b40c243c2 100644 --- a/web/packages/tca-layout/src/modules/git-oauth/index.tsx +++ b/web/packages/tca-layout/src/modules/git-oauth/index.tsx @@ -1,58 +1,40 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -/** - * 所有团队 - */ - import React, { useEffect } from 'react'; -import ReactDOM from 'react-dom'; -import { getQuery } from '@src/utils'; import { useParams } from 'react-router-dom'; - -import { Spin, message, Layout } from 'coding-oa-uikit'; -// import { t } from '@src/i18n/i18next'; +import { useTranslation } from 'react-i18next'; +import Loading from '@tencent/micro-frontend-shared/component/loading'; +import { getURLSearch } from '@tencent/micro-frontend-shared/util/route'; +import { PostMessageType, PostMessageCode, postMessageToTarget } from '@tencent/micro-frontend-shared/util/window'; + +import { message } from 'coding-oa-uikit'; + +import Container from '@src/component/container'; +import { UserAPI } from '@plat/api'; -import { getOAuthCallBack } from '@src/services/user'; - -const { Content } = Layout; - const GitOAuth = () => { - const containerNode = document.getElementById('container'); - const query = getQuery(); - const { scm_platform_name }: any = useParams(); + const query = getURLSearch(); + const { scmPlatformName }: any = useParams(); + const { t } = useTranslation(); useEffect(() => { - const opener = window.opener; - getOAuthCallBack(scm_platform_name,query).then(()=>{ - message.success('授权成功'); - opener.postMessage('oauth succeeded',opener.location.origin); - }).catch(()=>{ - message.error('授权失败'); - opener.postMessage('oauth failed',opener.location.origin); - }).finally(()=>{ - window.close(); - }); + const { opener } = window; + UserAPI.getOAuthCallback(scmPlatformName, query).then(() => { + message.success(t('OAuth授权成功')); + postMessageToTarget(opener, { code: PostMessageCode.SUCCESS, type: PostMessageType.GIT_OAUTH }); + }) + .catch(() => { + message.error(t('OAuth授权失败')); + postMessageToTarget(opener, { code: PostMessageCode.FAIL, type: PostMessageType.GIT_OAUTH }); + }) + .finally(() => { + window.close(); + }); }, []); return ( - <> - {containerNode - && ReactDOM.createPortal( - - - , - containerNode, - )} - + + + ); }; export default GitOAuth; - \ No newline at end of file diff --git a/web/packages/tca-layout/src/modules/home/banner.tsx b/web/packages/tca-layout/src/modules/home/banner.tsx new file mode 100644 index 000000000..b6fefb795 --- /dev/null +++ b/web/packages/tca-layout/src/modules/home/banner.tsx @@ -0,0 +1,94 @@ + +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { Button, Carousel } from 'coding-oa-uikit'; +import { getMetaContent } from '@tencent/micro-frontend-shared/util'; +import cn from 'classnames'; + +// 项目内 +import CodeBannerPng from '@src/images/code-banner.png'; +import { isEnableManage } from '@plat/util'; +import { getManageRouter } from '@src/utils/getRoutePath'; +import routes from '@plat/routes'; +import { SHOW_MANAGE_BTN } from '@plat/modules/home'; +import s from './style.scss'; + +// 开源地址 +const GITHUB_URL = getMetaContent('GITHUB_URL'); + +// 获取当前第一个路由 +const path = routes[0]?.path || '/'; +const router = path instanceof Array ? path[0] : path; + +const Banner = () => { + const history = useHistory(); + const { t } = useTranslation(); + + return ( +
+
+
+ +
+
+
+ +
+

腾讯云代码分析

+

+ 用心关注每行代码迭代、助力传承卓越代码文化! +
+ 精准跟踪管理代码分析发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码,以及度量代码复杂度、重复代码、代码统计。 +

+
+ + {SHOW_MANAGE_BTN && isEnableManage() && ( + + )} +
+
+ {GITHUB_URL &&
+

我们开源啦

+

+ 用心关注每行代码迭代、助力传承卓越代码文化! +
+ 精准跟踪管理代码分析发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码,以及度量代码复杂度、重复代码、代码统计。 +

+
+ +
+
} +
+
+
+ ); +}; + +export default Banner; diff --git a/web/packages/tca-layout/src/modules/home/footer.tsx b/web/packages/tca-layout/src/modules/home/footer.tsx new file mode 100644 index 000000000..66fea42a6 --- /dev/null +++ b/web/packages/tca-layout/src/modules/home/footer.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Layout } from 'coding-oa-uikit'; + +// 项目内 +import { FOOTER_DESC } from '@plat/modules/home'; +import s from './style.scss'; + +const Footer = () => ( + +
+
+

{FOOTER_DESC}

+

Copyright © 1998 - {new Date().getFullYear()} Tencent. All Rights Reserved.

+
+
+
+); + +export default Footer; diff --git a/web/packages/tca-layout/src/modules/home/header.tsx b/web/packages/tca-layout/src/modules/home/header.tsx new file mode 100644 index 000000000..50e704189 --- /dev/null +++ b/web/packages/tca-layout/src/modules/home/header.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Tag, Tooltip } from 'coding-oa-uikit'; +import { getMetaContent } from '@tencent/micro-frontend-shared/util'; + +// 模块内 +import GitHubSvg from '@src/images/github.svg'; +import LayoutHeader from '@src/component/layout-header'; + +// 通过meta版本名称来定义是否显示Tag +const VERSION_NAME = getMetaContent('VERSION_NAME'); +// github url,用于标记是否显示开源地址 +const GITHUB_URL = getMetaContent('GITHUB_URL'); + +const Header = () => + {VERSION_NAME && {VERSION_NAME}} + } + rightContent={<> + {GITHUB_URL && document.body}> + + + + } + } />; + +export default Header; diff --git a/web/packages/tca-layout/src/modules/home/index.tsx b/web/packages/tca-layout/src/modules/home/index.tsx index df76f113a..e917c9da9 100644 --- a/web/packages/tca-layout/src/modules/home/index.tsx +++ b/web/packages/tca-layout/src/modules/home/index.tsx @@ -1,229 +1,29 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React, { useEffect, useState } from 'react'; -import ReactDOM from 'react-dom'; -import { useHistory } from 'react-router-dom'; -import { Layout, Button, Tabs } from 'coding-oa-uikit'; +/** + * 首页 + * biz-start + * 目前适用于全平台 + * biz-end + */ +import React from 'react'; +import { Layout } from 'coding-oa-uikit'; // 项目内 -import { t } from '@src/i18n/i18next'; -import { enterpriseInfo } from '@src/utils/config'; -import { getHomeRouter, getTeamsRouter } from '@src/utils/getRoutePath'; - -import LangSvg from '@src/images/home/server/lang.svg'; -import ArchSvg from '@src/images/home/server/arch.svg'; -import CustomSvg from '@src/images/home/server/custom.svg'; -import ReportSvg from '@src/images/home/server/report.svg'; -import ToolSvg from '@src/images/home/server/tools.svg'; -import ScanSvg from '@src/images/home/server/scan.svg'; -import CodeBannerPng from '@src/images/code-banner.png'; - -import scene01 from '@src/images/home/scene/scene01.svg'; -import scene02 from '@src/images/home/scene/scene02.svg'; -import scene03 from '@src/images/home/scene/scene03.svg'; -import customers01 from '@src/images/home/customers/customers01.png'; -import customers02 from '@src/images/home/customers/customers02.png'; -import customers03 from '@src/images/home/customers/customers03.png'; -import customers04 from '@src/images/home/customers/customers04.png'; -import customers05 from '@src/images/home/customers/customers05.png'; -import customers06 from '@src/images/home/customers/customers06.png'; +import Container from '@src/component/container'; +import Header from './header'; +import Banner from './banner'; +import Section from './section'; +import Footer from './footer'; import s from './style.scss'; -const customers = [customers01, customers02, customers03, customers04, customers05, customers06]; - -const { Header, Content, Footer } = Layout; - -const HeaderRender = () => ( -
- - -
{enterpriseInfo.name}
-
-
-
-); - -const BannerRender = () => { - const history = useHistory(); - const onClick = () => { - history.push(getTeamsRouter()); - }; - return ( -
-
-
- -
-
-
-
-

腾讯云代码分析

-

- 用心关注每行代码迭代、助力传承卓越代码文化! -
- 精准跟踪管理代码分析发现的代码质量缺陷、代码规范、代码安全漏洞、无效代码,以及度量代码复杂度、重复代码、代码统计。 -

-
- -
-
-
-
- ); -}; - -const featureItems = [ - { - title: '稳定可靠的架构', - desc: '采用分布式云原生架构,支持灵活扩缩容,执行更快更稳定。', - img: ArchSvg, - key: 1, - }, - { - title: '多工具支持', - desc: '已集成众多自研、知名开源工具等,采用分层分离架构,满足快速自助管理工具。', - img: ToolSvg, - key: 2, - }, - { - title: '多语言覆盖', - desc: '支持29种编程语言,覆盖常见常用编程语言。', - img: LangSvg, - key: 3, - }, - { - title: '自定义质量指标', - desc: '自定义代码质量检测标准,逐步优化代码质量。', - img: CustomSvg, - key: 4, - }, - { - title: '增量全量分析', - desc: '增量分析快速发现问题,全量分析保证问题全覆盖。', - img: ScanSvg, - key: 5, - }, - { - title: '全方位质量报告', - desc: '图形化可视报告,轻松监管代码综合质量趋势。', - img: ReportSvg, - key: 6, - }, -]; - -const FeatureSectionRender = () => ( -
-

产品特性

-
- {/*

服务优势

*/} -
- {featureItems.map(item => ( -
-
- -
-
{item.title}
-
{item.desc}
-
- ))} -
-
-
-); - -const FooterRender = () => { - const [year, setYear] = useState(); - useEffect(() => { - const today = new Date(); - setYear(today.getFullYear()); - }, []); - return ( -
-
-
-

仅限于调试、测试、体验

-

Copyright © 1998 - {year} Tencent. All Rights Reserved.

-
-
-
- ); -}; - -const Home = () => { - const containerNode = document.getElementById('container'); - return ( - <> - {containerNode - && ReactDOM.createPortal( -
- - - - -
-

应用场景

- - -
-

腾讯云代码分析支持多语种代码工程质量的监控与分析,可进行增量、全量分析,精确追踪引入问题的责任人,聚合计算代码数据,输出报告。

- -
-
- -
-

支持功能分支和主干开发等研发模式,监控代码合流,门禁及时拦截并通知反馈。

- -
-
- -
-
-

腾讯云代码分析采用分布式客户端,支持云端分析、本地化分析、流水线调度分析等使用场景,满足多样化的研发环境。

-

用户可以直接在腾讯云代码分析 SaaS 平台上接入代码库进行云端分析。

-

用户可下载客户端,在本地机器上执行代码分析。

-

用户可通过 API 开放接口,自行与开源或自研的 DevOps 平台快速集成,满足各类 CI 流水线构建环节的代码分析。

-
- -
-
-
-
-
-

客户案例

-
- { - customers.map((src: any, index: number) => ( -
- - - -
- )) - } -
-
+const Home = () => +
+
+ + +
+ +
+
+
; -
- -
, - containerNode, - )} - - ); -}; export default Home; diff --git a/web/packages/tca-layout/src/modules/home/section.tsx b/web/packages/tca-layout/src/modules/home/section.tsx new file mode 100644 index 000000000..57962f0a9 --- /dev/null +++ b/web/packages/tca-layout/src/modules/home/section.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { Tabs } from 'coding-oa-uikit'; + +// 项目内 +import LangSvg from '@src/images/home/server/lang.svg'; +import ArchSvg from '@src/images/home/server/arch.svg'; +import CustomSvg from '@src/images/home/server/custom.svg'; +import ReportSvg from '@src/images/home/server/report.svg'; +import ToolSvg from '@src/images/home/server/tools.svg'; +import ScanSvg from '@src/images/home/server/scan.svg'; +import scene01 from '@src/images/home/scene/scene01.svg'; +import scene02 from '@src/images/home/scene/scene02.svg'; +import scene03 from '@src/images/home/scene/scene03.svg'; +import customers01 from '@src/images/home/customers/customers01.png'; +import customers02 from '@src/images/home/customers/customers02.png'; +import customers03 from '@src/images/home/customers/customers03.png'; +import customers04 from '@src/images/home/customers/customers04.png'; +import customers05 from '@src/images/home/customers/customers05.png'; +import customers06 from '@src/images/home/customers/customers06.png'; + +import s from './style.scss'; + +const featureItems = [ + { + title: '稳定可靠的架构', + desc: '采用分布式云原生架构,支持灵活扩缩容,执行更快更稳定。', + img: ArchSvg, + key: 1, + }, + { + title: '多工具支持', + desc: '已集成众多自研、知名开源工具等,采用分层分离架构,满足快速自助管理工具。', + img: ToolSvg, + key: 2, + }, + { + title: '多语言覆盖', + desc: '支持29种编程语言,覆盖常见常用编程语言。', + img: LangSvg, + key: 3, + }, + { + title: '自定义质量指标', + desc: '自定义代码质量检测标准,逐步优化代码质量。', + img: CustomSvg, + key: 4, + }, + { + title: '增量全量分析', + desc: '增量分析快速发现问题,全量分析保证问题全覆盖。', + img: ScanSvg, + key: 5, + }, + { + title: '全方位质量报告', + desc: '图形化可视报告,轻松监管代码综合质量趋势。', + img: ReportSvg, + key: 6, + }, +]; + +const customers = [customers01, customers02, customers03, customers04, customers05, customers06]; + +const Section = () => <> +
+

产品特性

+
+ {/*

服务优势

*/} +
+ {featureItems.map(item => ( +
+
+ +
+
{item.title}
+
{item.desc}
+
+ ))} +
+
+
+
+

应用场景

+ + +
+

腾讯云代码分析支持多语种代码工程质量的监控与分析,可进行增量、全量分析,精确追踪引入问题的责任人,聚合计算代码数据,输出报告。

+ +
+
+ +
+

支持功能分支和主干开发等研发模式,监控代码合流,门禁及时拦截并通知反馈。

+ +
+
+ +
+
+

腾讯云代码分析采用分布式客户端,支持云端分析、本地化分析、流水线调度分析等使用场景,满足多样化的研发环境。

+

用户可以直接在腾讯云代码分析 SaaS 平台上接入代码库进行云端分析。

+

用户可下载客户端,在本地机器上执行代码分析。

+

用户可通过 API 开放接口,自行与开源或自研的 DevOps 平台快速集成,满足各类 CI 流水线构建环节的代码分析。

+
+ +
+
+
+
+
+

客户案例

+
+ { + customers.map((src: any, index: number) => ( +
+ + + +
+ )) + } +
+
+; + +export default Section; diff --git a/web/packages/tca-layout/src/modules/home/style.scss b/web/packages/tca-layout/src/modules/home/style.scss index 8014c6a6b..3f69a0d6e 100644 --- a/web/packages/tca-layout/src/modules/home/style.scss +++ b/web/packages/tca-layout/src/modules/home/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; $content-max-width: 1180px; $foot-height: 150px; @@ -58,6 +58,13 @@ $content-min-height: $foot-height + 48px; .right { float: right; + .github { + img { + vertical-align: middle; + height: 24px; + } + } + .btn { width: 100px; height: 30px; @@ -68,7 +75,6 @@ $content-min-height: $foot-height + 48px; } .home .content { - padding-top: 12px; min-height: calc(100vh - #{$content-min-height}); overflow: hidden; @@ -313,4 +319,4 @@ $content-min-height: $foot-height + 48px; } } } -} +} \ No newline at end of file diff --git a/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx b/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx index bcb61c84d..3d1c449d7 100644 --- a/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx +++ b/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx @@ -1,24 +1,22 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React, { useState, useEffect } from 'react'; import { Link, useHistory } from 'react-router-dom'; import classnames from 'classnames'; -import { Breadcrumb, Select } from 'coding-oa-uikit'; +import { Tag, Breadcrumb, Select, Space } from 'coding-oa-uikit'; import AngleRight from 'coding-oa-uikit/lib/icon/AngleRight'; -import { filter } from 'lodash'; // 项目内 -import { getHomeRouter, getTeamRouter, getTeamsRouter, getProjectRouter } from '@src/utils/getRoutePath'; -import { enterpriseInfo } from '@src/utils/config'; +import { getMetaContent } from '@tencent/micro-frontend-shared/util'; +import { getTeamRouter, getTeamsRouter, getProjectRouter, getHomeRouter } from '@src/utils/getRoutePath'; +import HomeSvg from '@src/images/home.svg'; +import LogoIco from '@src/images/favicon.ico'; import { getProjects } from '@src/services/team'; // 模块内 import s from './style.scss'; +// 通过meta版本名称来定义是否显示Tag +const VERSION_NAME = getMetaContent('VERSION_NAME'); + const { Option } = Select; interface IProps { @@ -35,10 +33,8 @@ const Enterprise = ({ org, orgSid, teamName }: IProps) => { useEffect(() => { // 团队变更时重新获取项目列表 if (org.org_sid && teamName) { - getProjects(org.org_sid, null).then((response) => { - // 只显示未禁用的项目 - const activeProjects = filter(response, {status: 1}); - setProjectOptions(activeProjects.map((item: any) => ({ + getProjects(org.org_sid, null).then((response: any[]) => { + setProjectOptions(response.map((item: any) => ({ ...item, label: item.display_name, value: item.name, @@ -84,9 +80,10 @@ const Enterprise = ({ org, orgSid, teamName }: IProps) => { } return ( -
- {enterpriseInfo.name} -
+ + 腾讯云代码分析 + {VERSION_NAME && {VERSION_NAME}} +
); }; @@ -101,11 +98,11 @@ const Enterprise = ({ org, orgSid, teamName }: IProps) => { onMouseLeave={() => setHoveredLogo(false)} > diff --git a/web/packages/tca-layout/src/modules/layout/header/index.tsx b/web/packages/tca-layout/src/modules/layout/header/index.tsx index a054eb1d7..10d590920 100644 --- a/web/packages/tca-layout/src/modules/layout/header/index.tsx +++ b/web/packages/tca-layout/src/modules/layout/header/index.tsx @@ -1,18 +1,17 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - +/** + * 头部 + * biz-start + * 目前适用于体验、开源 + * biz-end + */ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import classnames from 'classnames'; -import { get } from 'lodash'; // 项目内 -import GlobalBreadcrumb from '@src/components/global-breadcrumb'; -import { UPDATE_BREADCRUMB_DATA } from '@src/components/global-breadcrumb/types'; +import GlobalBreadcrumb from '@src/component/global-breadcrumb'; +import { UPDATE_BREADCRUMB_DATA } from '@src/component/global-breadcrumb/types'; // 模块内 import s from './style.scss'; @@ -22,8 +21,7 @@ import Enterprise from './enterprise'; const Header = () => { const { orgSid, name }: any = useParams(); const storeDispatch = useDispatch(); - const APP = useSelector((state: any) => state.APP); - const org = get(APP, 'org', {}); + const org = useSelector((state: any) => state.APP)?.org ?? {}; const onBreadcrumbChange = (e: CustomEvent) => { const breadcrumbItems = e.detail; @@ -35,7 +33,9 @@ const Header = () => { useEffect(() => { window.addEventListener('on-breadcrumb-change', onBreadcrumbChange); - return window.removeEventListener('on-breadcrumb-change', onBreadcrumbChange); + return () => { + window.removeEventListener('on-breadcrumb-change', onBreadcrumbChange); + }; }, []); return ( diff --git a/web/packages/tca-layout/src/modules/layout/header/right-zone/index.tsx b/web/packages/tca-layout/src/modules/layout/header/right-zone/index.tsx index 309363e04..1ffb51895 100644 --- a/web/packages/tca-layout/src/modules/layout/header/right-zone/index.tsx +++ b/web/packages/tca-layout/src/modules/layout/header/right-zone/index.tsx @@ -1,36 +1,81 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - import React from 'react'; +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import classnames from 'classnames'; -import { Dropdown, Avatar } from 'coding-oa-uikit'; +import { Dropdown, Menu } from 'coding-oa-uikit'; +import { useStateStore } from '@tencent/micro-frontend-shared/hook-store'; +import UserAvatar from '@tencent/micro-frontend-shared/component/user-avatar'; + // 项目内 -import { useStateStore } from '@src/context/store'; -import { gUserImgUrl } from '@src/utils'; +import { NAMESPACE, UserState } from '@src/store/user'; +import { logout, getNickName } from '@src/utils'; +import { isEnableManage, getDocURL } from '@plat/util'; +import { getManageRouter, getUserProfileRouter, getUserAuthRouter } from '@src/utils/getRoutePath'; import s from './style.scss'; -import UserMenu from './user-menu'; +import Org from './org'; +import Language from './language'; interface IProps { org: any; } const RightZone = ({ org }: IProps) => { - const { userinfo } = useStateStore(); + const { userinfo } = useStateStore(NAMESPACE); + const { t } = useTranslation(); + + const isManage = /^\/manage/.test(window.location.pathname); + + const children =
+ + +
; return (
- -
- - + +
+ +
+
+ {userinfo.nickname} +
+
+ + {t('个人中心')} + + + {t('凭证管理')} + + {false} + {org.org_sid && ( + + + + )} + + + + {(isEnableManage() || userinfo?.is_superuser) && !isManage && ( + + {t('管理入口')} + + )} + + + {t('帮助文档')} + + + { + logout(t('退出登录中...')); + }} + > +
{t('退出')}
+
+ }> + {children}
); diff --git a/web/packages/tca-layout/src/modules/layout/header/right-zone/language.tsx b/web/packages/tca-layout/src/modules/layout/header/right-zone/language.tsx index 7d32b2b7a..7a09c0799 100644 --- a/web/packages/tca-layout/src/modules/layout/header/right-zone/language.tsx +++ b/web/packages/tca-layout/src/modules/layout/header/right-zone/language.tsx @@ -1,44 +1,36 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React, { useState } from 'react'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; import classnames from 'classnames'; import Cookies from 'universal-cookie'; import AngleRight from 'coding-oa-uikit/lib/icon/AngleRight'; -// import Dropdown from '@coding/coding-ui-kit/dropdown'; -// import Menu from '@coding/coding-ui-kit/menu'; import { Popover, message } from 'coding-oa-uikit'; -import { t } from '@src/i18n/i18next'; -// import { getMainDomain } from '@framework/utils/domain'; + +// 项目内 import s from './style.scss'; -const COOKIE_NAME = 'language'; -const DEFAULT_LANG = 'zh_CN'; +const COOKIE_NAME = 'i18next'; +const DEFAULT_LANG = 'zh-CN'; const LANG = [ - { key: 'zh_CN', name: '中文(简体)' }, - { key: 'zh_TW', name: '中文(繁体)' }, - { key: 'en_US', name: 'English(US)' }, + { key: 'zh-CN', name: '中文(简体)' }, + { key: 'zh-TW', name: '中文(繁体)' }, + { key: 'en-US', name: 'English(US)' }, ]; const cookies = new Cookies(); const LanguageUI = () => { - const [lang, setLang] = useState(cookies.get(COOKIE_NAME) || DEFAULT_LANG); + const { t, i18n } = useTranslation(); + const lang = cookies.get(COOKIE_NAME) ?? DEFAULT_LANG; + const { name: langText = '' } = LANG.find(({ key }) => lang === key) || {}; const onChange = (key: string) => { - // cookies.set(COOKIE_NAME, key, { path: '/', domain: getMainDomain() }); - cookies.set(COOKIE_NAME, key, { path: '/' }); - setLang(key); + i18n.changeLanguage(key); message.loading(t('语言切换中...')); const timer = setTimeout(() => { - window.location.reload(); clearTimeout(timer); + window.location.reload(); }, 300); }; - const { name: langText = '' } = LANG.find(({ key }) => lang === key) || {}; return ( { +const OrgUI = ({ name }: IProps) => { const [orgs, setOrgs] = useState>([]); const history = useHistory(); + const { t } = useTranslation(); const onChange = (item: any) => { message.loading(t('团队切换中...'), 0.3); @@ -32,8 +29,8 @@ const OrgUI = ({ org }: IProps) => { }; useEffect(() => { - getTeams({ limit: 100 }).then((response) => { - setOrgs(response.results.filter((item: any) => !(item.status > STATUS_ENUM.ACTIVE))); + getTeams({ limit: 100 }).then(({ results }) => { + setOrgs((results as any[]).filter((item: any) => !(item.status > OrgStatusEnum.ACTIVE))); }); }, []); @@ -57,9 +54,9 @@ const OrgUI = ({ org }: IProps) => { >
- {org.name} + {name[0].toUpperCase()} - {org.name} + {name} diff --git a/web/packages/tca-layout/src/modules/layout/header/right-zone/style.scss b/web/packages/tca-layout/src/modules/layout/header/right-zone/style.scss index a194894c8..1d8c5343e 100644 --- a/web/packages/tca-layout/src/modules/layout/header/right-zone/style.scss +++ b/web/packages/tca-layout/src/modules/layout/header/right-zone/style.scss @@ -1,4 +1,5 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; + .right-zone { display: inline-flex; align-items: center; diff --git a/web/packages/tca-layout/src/modules/layout/header/right-zone/user-menu.tsx b/web/packages/tca-layout/src/modules/layout/header/right-zone/user-menu.tsx deleted file mode 100644 index 789f8a28d..000000000 --- a/web/packages/tca-layout/src/modules/layout/header/right-zone/user-menu.tsx +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React from 'react'; -import { Menu, Avatar } from 'coding-oa-uikit'; -import { Link } from 'react-router-dom'; -import classnames from 'classnames'; - -// 项目内 -import { t } from '@src/i18n/i18next'; -import { gUserImgUrl, logout } from '@src/utils'; -import { getManageRouter, DOC_PATH } from '@src/utils/getRoutePath'; -import Language from './language'; -import Org from './org'; -import s from './style.scss'; - -const menu = (userinfo: any, org: any) => ( - -
- -
-
- {userinfo.nickname} -
- {/*
- {user.email} -
*/} -
-
- - {t('个人中心')} - - - {t('凭证管理')} - - {userinfo.is_superuser && ( - - {t('管理入口')} - - )} - {org.org_sid && ( - - - - )} - - - - - - {t('帮助文档')} - - - { - logout(t('退出登录中...')); - }} - > -
{t('退出')}
-
-
-); - -export default menu; diff --git a/web/packages/tca-layout/src/modules/layout/header/style.scss b/web/packages/tca-layout/src/modules/layout/header/style.scss index 1c10c31f2..9e376facc 100644 --- a/web/packages/tca-layout/src/modules/layout/header/style.scss +++ b/web/packages/tca-layout/src/modules/layout/header/style.scss @@ -1,4 +1,4 @@ -@import "@src/common/style/color.scss"; +@import "@tencent/micro-frontend-shared/style/color.scss"; $zindex-navbar: 1000 !default; $height: 48px; @@ -25,15 +25,6 @@ $search-input-left: 12px; box-shadow: 0 1px $grey-3; background: $white; z-index: $zindex-navbar; - - .beta { - display: inline-block; - margin-left: 12px; - color: $grey-8; - background-color: $grey-2; - border: none; - vertical-align: text-bottom; - } } .left-wrap { @@ -85,20 +76,11 @@ $search-input-left: 12px; white-space: nowrap; font-weight: 500; max-width: 280px; - margin-left: 8px; - margin-right: 8px; - // color: $grey-8; } .right-wrap { position: relative; height: $height; - margin-left: auto; // float to right under flexbox + margin-left: auto; white-space: nowrap; - // z-index: 9; - // background: white; - - // > * { - // vertical-align: middle; - // } } diff --git a/web/packages/tca-layout/src/modules/layout/manage/index.tsx b/web/packages/tca-layout/src/modules/layout/manage/index.tsx index 08d545d0b..e9bf4da7c 100644 --- a/web/packages/tca-layout/src/modules/layout/manage/index.tsx +++ b/web/packages/tca-layout/src/modules/layout/manage/index.tsx @@ -1,40 +1,20 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - - +/** + * 后台管理 nav + * biz-start + * 目前适用于体验、开源 + * biz-end + */ import React from 'react'; -import { useHistory } from 'react-router-dom'; -import { Button } from 'coding-oa-uikit'; // 项目内 import Header from '@src/modules/layout/header'; -import { useStateStore } from '@src/context/store'; -import { getHomeRouter } from '@src/utils/getRoutePath'; -import SiderBarManage from './siderbar-manage'; -import s from './style.scss' - +import SideBar from './sidebar'; function Manage() { - const history = useHistory(); - const { userinfo } = useStateStore(); - if (!userinfo.is_superuser) { - return
-

403

-

没有权限访问后台管理页面

- -
- } return ( <>
- + ); } diff --git a/web/packages/tca-layout/src/modules/layout/manage/sidebar.tsx b/web/packages/tca-layout/src/modules/layout/manage/sidebar.tsx new file mode 100644 index 000000000..52ab8b9ae --- /dev/null +++ b/web/packages/tca-layout/src/modules/layout/manage/sidebar.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +// 项目内 +import LayoutMenu from '@src/component/layout-menu'; +import { NAVS as menus } from '@plat/modules/manage'; + + +const SiderBar = () => ; + +export default SiderBar; diff --git a/web/packages/tca-layout/src/modules/layout/manage/siderbar-manage/index.tsx b/web/packages/tca-layout/src/modules/layout/manage/siderbar-manage/index.tsx deleted file mode 100644 index a5960b7a6..000000000 --- a/web/packages/tca-layout/src/modules/layout/manage/siderbar-manage/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - - -import React from 'react'; -// 项目内 -import MenuLayout from '@src/components/menu-layout'; -import menus from './menus'; - -const SiderBar = () => ; - -export default SiderBar; diff --git a/web/packages/tca-layout/src/modules/layout/manage/style.scss b/web/packages/tca-layout/src/modules/layout/manage/style.scss deleted file mode 100644 index c27e87589..000000000 --- a/web/packages/tca-layout/src/modules/layout/manage/style.scss +++ /dev/null @@ -1,11 +0,0 @@ -.manage-not-prem { - position: absolute; - left: 0; - top: 0; - padding-top: 200px; - width: 100%; - height: 100%; - text-align: center; - background: #fff; - z-index: 999; -} diff --git a/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/index.tsx b/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/index.tsx deleted file mode 100644 index a852551b4..000000000 --- a/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - - -import React from 'react'; -import { useParams } from 'react-router-dom'; -// 项目内 -import MenuLayout from '@src/components/menu-layout'; -import getMenus from './menus'; - -const SiderBar = () => { - const { orgSid, name }: any = useParams(); - return ( - - ); -}; - -export default SiderBar; diff --git a/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/menus.tsx b/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/menus.tsx deleted file mode 100644 index d4bd0c12c..000000000 --- a/web/packages/tca-layout/src/modules/layout/project/components/siderbar-project/menus.tsx +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2021-2022 THL A29 Limited -// -// This source code file is made available under MIT License -// See LICENSE for details -// ============================================================================== - -import React from 'react'; - -// 项目内 -import { t } from '@src/i18n/i18next'; -import { MenuItem } from '@src/components/menu-layout'; -import Repos from 'coding-oa-uikit/lib/icon/Repos'; -import Scan from 'coding-oa-uikit/lib/icon/Scan'; -import Template from 'coding-oa-uikit/lib/icon/Template'; -import Api from 'coding-oa-uikit/lib/icon/Api'; -import Group from 'coding-oa-uikit/lib/icon/Group'; -import TeamOverview from 'coding-oa-uikit/lib/icon/TeamOverview'; -import { API_DOC_PATH } from '@src/utils/getRoutePath'; - -const getTeamMenus = (orgSid: string, name: string): MenuItem[] => [ - { - icon: , - title: t('仓库登记'), - link: `/t/${orgSid}/p/${name}/repos`, - key: 'repos', - regexMatch: /^\/t\/[^/]+\/p\/[^/]+\/repos/i, - }, - { - icon: , - title: t('代码分析'), - key: 'code-analysis', - childrens: [ - { - title: t('分支项目'), - link: `/t/${orgSid}/p/${name}/code-analysis/repos/projects`, - key: 'projects', - regexMatch: /(^\/t\/[^/]+\/p\/[^/]+\/code-analysis\/repos\/\d+\/projects)|(^\/t\/[^/]+\/p\/[^/]+\/code-analysis\/repos\/projects)/i, - }, - { - title: t('分析方案'), - link: `/t/${orgSid}/p/${name}/code-analysis/repos/schemes`, - key: 'schemes', - regexMatch: /(^\/t\/[^/]+\/p\/[^/]+\/code-analysis\/repos\/\d+\/schemes)|(^\/t\/[^/]+\/p\/[^/]+\/code-analysis\/repos\/schemes)/i, - }, - ], - }, - { - icon: