├── .editorconfig ├── .env ├── .env.development ├── .env.site ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.zh-CN.yml │ ├── config.yml │ └── feature-report.zh-CN.yml ├── PULL_REQUEST_TEMPLATE.md ├── configs │ └── typos_config.toml ├── dependabot.yml └── workflows │ ├── issue-assignees.temp.yml │ ├── issue-help-wanted.temp.yml │ ├── issue-mark-duplicate.temp.yml │ ├── issue-reply.temp.yml │ ├── issue-synchronize.temp.yml │ ├── pr-spelling.temp.yml │ ├── preview-publish.yml │ └── pull-request.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc.js ├── CHANGELOG.md ├── LICENSE ├── README-zh_CN.md ├── README.md ├── docs └── docs-starter.png ├── index.html ├── mock ├── api │ └── getList.js └── index.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── robots.txt ├── src ├── assets │ ├── image │ │ ├── assets-login-bg-black.png │ │ └── assets-login-bg-white.png │ └── svg │ │ ├── assets-logo-full.svg │ │ ├── assets-product-1.svg │ │ ├── assets-product-2.svg │ │ ├── assets-product-3.svg │ │ ├── assets-product-4.svg │ │ ├── assets-result-403.svg │ │ ├── assets-result-404.svg │ │ ├── assets-result-500.svg │ │ ├── assets-result-browser-incompatible.svg │ │ ├── assets-result-maintenance.svg │ │ ├── assets-result-network-error.svg │ │ ├── assets-setting-auto.svg │ │ ├── assets-setting-dark.svg │ │ ├── assets-setting-light.svg │ │ └── assets-t-logo.svg ├── components │ ├── Board │ │ ├── index.module.less │ │ └── index.tsx │ ├── DatePicker │ │ └── index.tsx │ └── ErrorPage │ │ ├── index.module.less │ │ └── index.tsx ├── configs │ ├── color.ts │ └── host.ts ├── global.d.ts ├── hooks │ └── useDynamicChart.ts ├── layouts │ ├── components │ │ ├── AppLayout.module.less │ │ ├── AppLayout.tsx │ │ ├── AppRouter.module.less │ │ ├── AppRouter.tsx │ │ ├── Footer.tsx │ │ ├── Header │ │ │ ├── HeaderIcon.module.less │ │ │ ├── HeaderIcon.tsx │ │ │ ├── Search.module.less │ │ │ ├── Search.tsx │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Menu.module.less │ │ ├── Menu.tsx │ │ ├── MenuLogo.tsx │ │ ├── Page.module.less │ │ ├── Page.tsx │ │ └── Setting │ │ │ ├── RadioColor.module.less │ │ │ ├── RadioColor.tsx │ │ │ ├── RadioRect.module.less │ │ │ ├── RadioRect.tsx │ │ │ ├── index.module.less │ │ │ └── index.tsx │ ├── index.module.less │ └── index.tsx ├── main.tsx ├── modules │ ├── global │ │ └── index.ts │ ├── list │ │ ├── base.ts │ │ ├── card.ts │ │ └── select.ts │ ├── store.ts │ └── user │ │ └── index.ts ├── pages │ ├── Dashboard │ │ ├── Base │ │ │ ├── chart.ts │ │ │ ├── components │ │ │ │ ├── MiddleChart.module.less │ │ │ │ ├── MiddleChart.tsx │ │ │ │ ├── Overview.module.less │ │ │ │ ├── Overview.tsx │ │ │ │ ├── RankList.module.less │ │ │ │ ├── RankList.tsx │ │ │ │ ├── TopPanel.module.less │ │ │ │ └── TopPanel.tsx │ │ │ ├── constant.ts │ │ │ └── index.tsx │ │ └── Detail │ │ │ ├── chart.ts │ │ │ ├── components │ │ │ ├── MonthPurchase.tsx │ │ │ ├── PurchaseThrend.module.less │ │ │ ├── PurchaseTrend.tsx │ │ │ ├── Satisfaction.module.less │ │ │ └── Satisfaction.tsx │ │ │ ├── constant.ts │ │ │ └── index.tsx │ ├── Detail │ │ ├── Advanced │ │ │ ├── components │ │ │ │ ├── Base.module.less │ │ │ │ ├── Base.tsx │ │ │ │ ├── Detail.tsx │ │ │ │ ├── Product.tsx │ │ │ │ ├── ProductCard.module.less │ │ │ │ ├── ProductCard.tsx │ │ │ │ └── Progress.tsx │ │ │ ├── consts.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Base │ │ │ ├── consts.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Deploy │ │ │ ├── chart.ts │ │ │ ├── components │ │ │ │ ├── BottomTable.module.less │ │ │ │ ├── BottomTable.tsx │ │ │ │ ├── DynamicLineChart.tsx │ │ │ │ ├── ManagementPopup.module.less │ │ │ │ ├── ManagementPopup.tsx │ │ │ │ ├── TopChart.module.less │ │ │ │ └── TopChart.tsx │ │ │ ├── constant.ts │ │ │ └── index.tsx │ │ └── Secondary │ │ │ ├── consts.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ ├── Form │ │ ├── Base │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── Step │ │ │ ├── components │ │ │ ├── StepFour.tsx │ │ │ ├── StepOne.tsx │ │ │ ├── StepThree.tsx │ │ │ ├── StepTwo.tsx │ │ │ ├── index.module.less │ │ │ └── index.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ ├── List │ │ ├── Base │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Card │ │ │ ├── components │ │ │ │ ├── ProductCard.module.less │ │ │ │ └── ProductCard.tsx │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Select │ │ │ ├── components │ │ │ │ └── SearchForm.tsx │ │ │ ├── consts.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── Tree │ │ │ ├── consts.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ ├── Login │ │ ├── components │ │ │ ├── Header │ │ │ │ ├── index.module.less │ │ │ │ └── index.tsx │ │ │ ├── Login │ │ │ │ ├── index.module.less │ │ │ │ └── index.tsx │ │ │ └── Register │ │ │ │ ├── index.module.less │ │ │ │ └── index.tsx │ │ ├── hooks │ │ │ └── useCountDown.ts │ │ ├── index.module.less │ │ └── index.tsx │ ├── Result │ │ ├── 403 │ │ │ └── index.tsx │ │ ├── 404 │ │ │ └── index.tsx │ │ ├── 500 │ │ │ └── index.tsx │ │ ├── BrowserIncompatible │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Fail │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── Maintenance │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── NetworkError │ │ │ └── index.tsx │ │ ├── Success │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── index.module.less │ └── User │ │ ├── chart.ts │ │ ├── consts.ts │ │ ├── index.module.less │ │ └── index.tsx ├── router │ ├── index.ts │ └── modules │ │ ├── dashboard.ts │ │ ├── detail.ts │ │ ├── form.ts │ │ ├── list.ts │ │ ├── login.ts │ │ ├── others.ts │ │ ├── result.ts │ │ └── user.ts ├── services │ ├── contract.ts │ └── product.ts ├── styles │ ├── common.module.less │ └── index.less ├── types │ └── index.d.ts └── utils │ ├── chart.ts │ ├── color.ts │ ├── path.ts │ └── request.ts ├── tsconfig.json └── vite.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # indicate this is the root of the project 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # 打包路径 根据项目不同按需配置 2 | VITE_BASE_URL = / 3 | 4 | NODE_ENV=production 5 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # 打包路径 2 | VITE_BASE_URL= / 3 | 4 | NODE_ENV=development 5 | -------------------------------------------------------------------------------- /.env.site: -------------------------------------------------------------------------------- 1 | # 打包路径 根据项目不同按需配置 2 | VITE_BASE_URL=https://static.tdesign.tencent.com/starter/react/ 3 | 4 | NODE_ENV=production 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build 2 | mock 3 | config 4 | public 5 | scripts 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: [ 4 | 'airbnb-base', 5 | 'prettier', 6 | 'plugin:react/recommended', 7 | 'plugin:import/typescript', 8 | 'plugin:@typescript-eslint/recommended', 9 | ], 10 | plugins: ['eslint-plugin-prettier'], 11 | parser: '@typescript-eslint/parser', 12 | env: { 13 | jest: true, 14 | }, 15 | settings: { 16 | react: { 17 | version: 'detect', 18 | }, 19 | }, 20 | rules: { 21 | 'no-shadow': 'off', 22 | 'no-param-reassign': ['error', { props: false }], 23 | 'no-console': 'off', 24 | 'no-plusplus': [ 25 | 'error', 26 | { 27 | allowForLoopAfterthoughts: true, 28 | }, 29 | ], 30 | 'react/display-name': 'off', 31 | // jsx 单引号 32 | 'jsx-quotes': [2, 'prefer-single'], 33 | 'import/no-cycle': 'off', // TODO: remove 34 | 'import/extensions': 'off', 35 | 'import/no-unresolved': 'off', 36 | 'import/order': 'off', 37 | 'import/prefer-default-export': 'off', 38 | 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], 39 | // 关闭variable必须全部大写规则 40 | '@typescript-eslint/naming-convention': [ 41 | 'error', 42 | { 43 | selector: 'variable', 44 | modifiers: ['const'], 45 | format: null, 46 | }, 47 | ], 48 | '@typescript-eslint/no-empty-function': 'off', 49 | '@typescript-eslint/no-explicit-any': 'off', 50 | '@typescript-eslint/ban-types': 'off', 51 | // 统一eslint prettier配置 52 | 'prettier/prettier': [ 53 | 'warn', 54 | {}, 55 | { 56 | usePrettierrc: true, 57 | }, 58 | ], 59 | }, 60 | }; 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.zh-CN.yml: -------------------------------------------------------------------------------- 1 | name: 反馈 Bug 2 | description: 通过 github 模板进行 Bug 反馈。 3 | title: "[组件名称] 描述问题的标题" 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | # 欢迎你的参与 9 | tdesign-react-starter 的 Issue 列表接受 bug 报告或是新功能请求。也可加入官方社区: 10 | 11 | 在发布一个 Issue 前,请确保: 12 | - 在 [常见问题](https://tdesign.tencent.com/about/faq)、[更新日志](https://tdesign.tencent.com/about/release) 和 [旧Issue列表](https://github.com/Tencent/tdesign-react-starter/issues?q=is%3Aissue) 中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正) 13 | - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。 14 | 15 | - type: input 16 | id: version 17 | attributes: 18 | label: tdesign-react-starter 版本 19 | description: 请检查在最新项目版本中能否重现此 issue。 20 | placeholder: 请填写 21 | validations: 22 | required: true 23 | 24 | - type: input 25 | id: reproduce 26 | attributes: 27 | label: 重现链接 28 | description: 请提供尽可能精简的 CodePen、CodeSandbox 或 GitHub 仓库的链接。请不要填无关链接,否则你的 Issue 将被关闭。 29 | placeholder: 请填写 30 | 31 | - type: textarea 32 | id: reproduceSteps 33 | attributes: 34 | label: 重现步骤 35 | description: 请清晰的描述重现该 Issue 的步骤,这能帮助我们快速定位问题。没有清晰重现步骤将不会被修复,标有 'need reproduction' 的 Issue 在 7 天内不提供相关步骤,将被关闭。 36 | placeholder: 请填写 37 | 38 | - type: textarea 39 | id: expect 40 | attributes: 41 | label: 期望结果 42 | placeholder: 请填写 43 | 44 | - type: textarea 45 | id: actual 46 | attributes: 47 | label: 实际结果 48 | placeholder: 请填写 49 | 50 | - type: input 51 | id: frameworkVersion 52 | attributes: 53 | label: 框架版本 54 | placeholder: Vue(3.2.0) 55 | 56 | - type: input 57 | id: browsersVersion 58 | attributes: 59 | label: 浏览器版本 60 | placeholder: Chrome(8.213.231.123) 61 | 62 | - type: input 63 | id: systemVersion 64 | attributes: 65 | label: 系统版本 66 | placeholder: MacOS(11.2.3) 67 | 68 | - type: input 69 | id: nodeVersion 70 | attributes: 71 | label: Node版本 72 | placeholder: 请填写 73 | 74 | - type: textarea 75 | id: remarks 76 | attributes: 77 | label: 补充说明 78 | description: 可以是遇到这个 bug 的业务场景、上下文等信息。 79 | placeholder: 请填写 80 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 使用 issue-helper 新建 4 | url: https://Tencent.github.io/tdesign/issue-helper/?lang=zh-CN&repo=Tencent/tdesign 5 | about: 使用 https://Tencent.github.io/tdesign/issue-helper/ 创建 issue,其中包含 bug 和 feature,表单提交更加严格。 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-report.zh-CN.yml: -------------------------------------------------------------------------------- 1 | name: 反馈新功能 2 | description: 通过 github 模板进行新功能反馈。 3 | title: "[组件名称] 描述问题的标题" 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | # 欢迎你的参与 9 | tdesign-react-starter 的 Issue 列表接受 bug 报告或是新功能请求。也可加入官方社区: 10 | 11 | 在发布一个 Issue 前,请确保: 12 | - 在 [常见问题](https://tdesign.tencent.com/about/faq)、[更新日志](https://tdesign.tencent.com/about/release) 和 [旧Issue列表](https://github.com/Tencent/tdesign-react-starter/issues?q=is%3Aissue) 中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正) 13 | - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。 14 | 15 | - type: textarea 16 | id: functionContent 17 | attributes: 18 | label: 这个功能解决了什么问题 19 | description: 请详尽说明这个需求的用例和场景。最重要的是:解释清楚是怎样的用户体验需求催生了这个功能上的需求。我们将考虑添加在现有 API 无法轻松实现的功能。新功能的用例也应当足够常见。 20 | placeholder: 请填写 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | id: functionalExpectations 26 | attributes: 27 | label: 你建议的方案是什么 28 | placeholder: 请填写 29 | validations: 30 | required: true 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ### 🤔 这个 PR 的性质是? 8 | 9 | - [ ] 日常 bug 修复 10 | - [ ] 新特性提交 11 | - [ ] 文档改进 12 | - [ ] 演示代码改进 13 | - [ ] 组件样式/交互改进 14 | - [ ] CI/CD 改进 15 | - [ ] 重构 16 | - [ ] 代码风格优化 17 | - [ ] 测试用例 18 | - [ ] 分支合并 19 | - [ ] 其他 20 | 21 | ### 🔗 相关 Issue 22 | 23 | 26 | 27 | ### 💡 需求背景和解决方案 28 | 29 | 34 | 35 | ### 📝 更新日志 36 | 37 | 40 | 41 | - fix(组件名称): 处理问题或特性描述 ... 42 | 43 | - [ ] 本条 PR 不需要纳入 Changelog 44 | 45 | ### ☑️ 请求合并前的自查清单 46 | 47 | ⚠️ 请自检并全部**勾选全部选项**。⚠️ 48 | 49 | - [ ] 文档已补充或无须补充 50 | - [ ] 代码演示已提供或无须提供 51 | - [ ] TypeScript 定义已补充或无须补充 52 | - [ ] Changelog 已提供或无须提供 53 | -------------------------------------------------------------------------------- /.github/configs/typos_config.toml: -------------------------------------------------------------------------------- 1 | files.extend-exclude = [ 2 | "package-lock.json", 3 | "src/configs/color.ts" 4 | ] -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Basic dependabot.yml file with 2 | # minimum configuration for two package managers 3 | 4 | version: 2 5 | updates: 6 | # Enable version updates for npm 7 | - package-ecosystem: "npm" 8 | # Look for `package.json` and `lock` files in the `root` directory 9 | directory: "/" 10 | # Check the npm registry for updates every day (weekdays) 11 | schedule: 12 | interval: "monthly" 13 | 14 | # Enable version updates for Docker 15 | - package-ecosystem: "docker" 16 | # Look for a `Dockerfile` in the `root` directory 17 | directory: "/" 18 | # Check for updates once a week 19 | schedule: 20 | interval: "monthly" 21 | -------------------------------------------------------------------------------- /.github/workflows/issue-assignees.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | name: Issue Add Assigness 3 | 4 | on: 5 | issues: 6 | types: [opened, edited] 7 | 8 | jobs: 9 | mark-duplicate: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: wow-actions/auto-comment@v1 13 | with: 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | issuesOpened: | 16 | 👋 @{{ author }},感谢给 TDesign 提出了 issue。 17 | 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。 18 | 19 | # https://docs.github.com/cn/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues 20 | - uses: 94dreamer/issue-assignees@main 21 | id: assignees 22 | with: 23 | project_name: ${{github.event.repository.name}} 24 | issue_title: ${{github.event.issue.title}} 25 | 26 | - run: echo ${{ steps.assignees.outputs.contributors }} 27 | - name: Add assigness 28 | if: steps.assignees.outputs.contributors != '' 29 | uses: actions-cool/issues-helper@v3 30 | with: 31 | actions: 'add-assignees' 32 | token: ${{ secrets.GITHUB_TOKEN }} 33 | issue-number: ${{ github.event.issue.number }} 34 | assignees: ${{ steps.assignees.outputs.contributors }} 35 | 36 | - run: | 37 | contributors=${{ steps.assignees.outputs.contributors }} 38 | contributorstring=${contributors//,/ @} 39 | echo "::set-output name=string::@$contributorstring" 40 | id: contributors 41 | 42 | - name: 通知贡献者 43 | if: steps.assignees.outputs.contributors != '' 44 | uses: actions-cool/maintain-one-comment@v2.0.0 45 | with: 46 | token: ${{ secrets.GITHUB_TOKEN }} 47 | body: | 48 | ♥️ 有劳 ${{ steps.contributors.outputs.string }} 尽快确认问题。 49 | 确认有效后将下一步计划和可能需要的时间回复给 @${{ github.event.issue.user.login }} 。 50 | 51 | number: ${{ github.event.issue.number }} 52 | body-include: "" 53 | -------------------------------------------------------------------------------- /.github/workflows/issue-help-wanted.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | name: Issue Help wanted 3 | on: 4 | issues: 5 | types: 6 | - labeled 7 | jobs: 8 | add-comment: 9 | if: github.event.label.name == 'help wanted' 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | steps: 14 | - name: Add comment 15 | uses: peter-evans/create-or-update-comment@v1 16 | with: 17 | issue-number: ${{ github.event.issue.number }} 18 | body: | 19 | 任何人都可以处理此问题。 20 | **请务必在您的 `pull request` 中引用此问题。** :sparkles: 21 | 感谢你的贡献! :sparkles: 22 | reactions: heart -------------------------------------------------------------------------------- /.github/workflows/issue-mark-duplicate.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | # 当在 issue 的 comment 回复类似 `Duplicate of #111` 这样的话,issue 将被自动打上 重复提交标签 并且 cloese 3 | name: Issue Mark Duplicate 4 | 5 | on: 6 | issue_comment: 7 | types: [created, edited] 8 | 9 | jobs: 10 | mark-duplicate: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: mark-duplicate 14 | uses: actions-cool/issues-helper@v2 15 | with: 16 | actions: "mark-duplicate" 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | duplicate-labels: "duplicate" 19 | close-issue: true 20 | -------------------------------------------------------------------------------- /.github/workflows/issue-reply.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | # 当被打上 Need Reproduce 标签时候,自动提示需要重现实例 3 | 4 | name: ISSUE_REPLY 5 | 6 | on: 7 | issues: 8 | types: [labeled] 9 | 10 | jobs: 11 | issue-reply: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Need Reproduce 15 | if: github.event.label.name == 'Need Reproduce' 16 | uses: actions-cool/issues-helper@v2 17 | with: 18 | actions: 'create-comment' 19 | issue-number: ${{ github.event.issue.number }} 20 | body: | 21 | 你好 @${{ github.event.issue.user.login }}, 我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击 [此处](https://codesandbox.io/) 创建一个 codesandbox 或者提供一个最小化的 GitHub 仓库。请确保选择准确的版本。 22 | -------------------------------------------------------------------------------- /.github/workflows/issue-synchronize.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | name: Issue Add Assigness 3 | 4 | on: 5 | issues: 6 | types: [opened, reopened] 7 | 8 | jobs: 9 | mark-duplicate: 10 | runs-on: ubuntu-latest 11 | steps: 12 | # https://docs.github.com/cn/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues 13 | - uses: 94dreamer/create-report@main 14 | with: 15 | wxhook: ${{ secrets.WX_HOOK_URL }} 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | type: 'issue' -------------------------------------------------------------------------------- /.github/workflows/pr-spelling.temp.yml: -------------------------------------------------------------------------------- 1 | # force copy from tencent/tdesign 2 | name: pr-spell-check 3 | on: [pull_request] 4 | 5 | jobs: 6 | run: 7 | name: Spell Check with Typos 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Check spelling 12 | uses: crate-ci/typos@master 13 | with: 14 | config: .github/configs/typos_config.toml 15 | -------------------------------------------------------------------------------- /.github/workflows/preview-publish.yml: -------------------------------------------------------------------------------- 1 | # 文件名建议统一为 preview-publish 2 | # 应用 preview.yml 的 demo 3 | name: PREVIEW_PUBLISH 4 | 5 | on: 6 | workflow_run: 7 | workflows: ["MAIN_PULL_REQUEST"] 8 | types: 9 | - completed 10 | 11 | jobs: 12 | call-preview: 13 | uses: Tencent/tdesign/.github/workflows/preview.yml@main 14 | secrets: 15 | TDESIGN_SURGE_TOKEN: ${{ secrets.TDESIGN_SURGE_TOKEN }} 16 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | # 文件名建议统一为 pull-request.yml 2 | # 应用 test-build.yml 的 demo 3 | # 要求 package.json 提供 lint test site:preview 4 | 5 | name: MAIN_PULL_REQUEST 6 | 7 | on: 8 | pull_request: 9 | branches: [develop, main, site] 10 | types: [opened, synchronize, reopened] 11 | 12 | jobs: 13 | call-test-build: 14 | uses: Tencent/tdesign/.github/workflows/test-build.yml@main 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /coverage 6 | 7 | # production 8 | /dist 9 | 10 | # misc 11 | .DS_Store 12 | .idea 13 | .VSCodeCounter 14 | 15 | # log 16 | npm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | 20 | # lock 文件 请根据自身项目或团队需求选择具体的包管理工具 并移除具体的ignore的lock文件 21 | yarn.lock 22 | pnpm-lock.yaml 23 | 24 | # code editor setting 25 | /.vscode 26 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | if [[ `uname` == 'Darwin' ]]; then 5 | PATH="/usr/local/bin:$PATH" 6 | fi 7 | 8 | npm run lint:fix 9 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: true, 7 | quoteProps: 'as-needed', 8 | jsxSingleQuote: true, 9 | trailingComma: 'all', 10 | bracketSpacing: true, 11 | jsxBracketSameLine: false, 12 | arrowParens: 'always', 13 | rangeStart: 0, 14 | rangeEnd: null, 15 | requirePragma: false, 16 | insertPragma: false, 17 | proseWrap: 'preserve', 18 | htmlWhitespaceSensitivity: 'css', 19 | vueIndentScriptAndStyle: false, 20 | endOfLine: 'lf', 21 | embeddedLanguageFormatting: 'auto', 22 | }; 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # Changelog 3 | 4 | ## 0.3.1 5 | ### 🚀 Features 6 | 7 | - 移除所有内置主题色相关代码,全部通过 tvision-color 计算获取 by @uyarn #144 8 | 9 | - 卡片统一默认样式为无边框 by @uyarn #144 10 | 11 | **Full Changelog**: https://github.com/Tencent/tdesign-react-starter/compare/0.3.0...0.3.1 12 | 13 | ## 0.3.0 14 | ❗ Breaking Changes 15 | 16 | - 统一使用`.env`文件区分环境 生产环境改为`release` by @uyarn in https://github.com/Tencent/tdesign-react-starter/pull/136 17 | 18 | 🚀 Features 19 | 20 | - 默认路由模式改为`history`路由 by @uyarn in https://github.com/Tencent/tdesign-react-starter/pull/136 21 | 22 | **Full Changelog**: https://github.com/Tencent/tdesign-react-starter/compare/0.2.0...0.3.0 23 | 24 | ## 0.2.0 25 | ### ❗ Breaking Changes 26 | 27 | - 升级组件库依赖至 0.43+ 更新主题色配色方案 by @uyarn in https://github.com/Tencent/tdesign-react-starter/pull/129 28 | 29 | ### 🚀 Features 30 | 31 | - 新增自定义颜色面板选择 by @uyarn in https://github.com/Tencent/tdesign-react-starter/pull/129 32 | 33 | ### 🐞 Bug Fixes 34 | 35 | - 修复卡片面板的标题丢失的问题 by @uyarn https://github.com/Tencent/tdesign-react-starter/pull/129 36 | 37 | **Full Changelog**: https://github.com/Tencent/tdesign-react-starter/compare/0.1.6...0.2.0 38 | 39 | ## 0.1.6 40 | ### Features 41 | 42 | - 升级组件库依赖至0.42+ 版本 43 | 44 | ### Bug Fixes 45 | 46 | - 修复部分页面样式展示的缺陷 47 | 48 | - 优化顶部菜单布局 49 | 50 | ## 0.1.5 51 | ## Features 52 | 53 | - 新增卡片列表页 by @xucz in https://github.com/Tencent/tdesign-react-starter/pull/91 54 | 55 | - 菜单路由配置`hidden`和`single`功能 by @xucz in https://github.com/Tencent/tdesign-react-starter/pull/95 56 | 57 | ## Bug Fixes 58 | 59 | - 同步DatePicker组件升级的改动 by @uyarn in https://github.com/Tencent/tdesign-react-starter/pull/87 60 | 61 | **Full Changelog**: https://github.com/Tencent/tdesign-react-starter/compare/0.1.4...0.1.5 62 | 63 | ## 0.1.4 64 | ## Features 65 | 66 | - 增加面包屑导航 67 | 68 | - 搜索框样式优化 69 | 70 | - Layout组件命名语义化 71 | 72 | - 图表主题功能优化 73 | 74 | ## 0.1.3 75 | 1. 升级tdesign-react 76 | 77 | 2. 替换为tdesign-react Card 组件 78 | 79 | 3. table样式优化 80 | 81 | ## 0.1.2 82 | - 升级axios、tdesign @xucz 83 | 84 | - fix: loss css token @uyarn 85 | 86 | - 修复图表文字重叠 @xucz 87 | 88 | ## 0.1.1 89 | ## Features 90 | 91 | - 新增登录页 #42 by @uyarn 92 | 93 | - Logo点击跳转首页 #45 by @aouos 94 | 95 | ## 0.1.0 96 | ## Bug Fixes 97 | 98 | - 修复页面主题色 by @xucz 99 | 100 | - 修复页面布局 101 | 102 | - 修复版本图表渲染问题 103 | 104 | ## Features 105 | 106 | - 增加数据Mock by @xucz 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-present TDesign 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /docs/docs-starter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/tdesign-react-starter/4a70384d5af80843b135d3e8bd8b1f0be34a779f/docs/docs-starter.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TDesign Starter 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 28 | 29 | 30 |
31 | 32 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /mock/api/getList.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs'); 2 | export default { 3 | url: '/api/get-list', 4 | method: 'get', 5 | response: () => { 6 | return { 7 | code: 0, 8 | msg: 'ok', 9 | data: { 10 | ...Mock.mock({ 11 | 'list|100': [ 12 | { 13 | 'index|+1': 1, 14 | 'status|1': '@natural(0, 4)', 15 | no: 'BH00@natural(01, 100)', 16 | name: '@city()办公用品采购项目', 17 | 'paymentType|1': '@natural(0, 1)', 18 | 'contractType|1': '@natural(0, 2)', 19 | updateTime: '2020-05-30 @date("HH:mm:ss")', 20 | amount: '@natural(10, 500),000,000', 21 | adminName: '@cname()', 22 | }, 23 | ], 24 | }), 25 | }, 26 | }; 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /mock/index.js: -------------------------------------------------------------------------------- 1 | import getList from './api/getList'; 2 | 3 | export default [getList]; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tencent/tdesign-react-starter", 3 | "version": "0.3.1", 4 | "private": true, 5 | "scripts": { 6 | "dev:mock": "vite --open --mode mock", 7 | "dev": "vite --open --mode development", 8 | "dev:linux": "vite --mode development", 9 | "build:test": "vite build --mode test", 10 | "build": "vite build --mode release", 11 | "build:site": "vite build --mode site", 12 | "site:preview": "npm run build && cp -r dist _site", 13 | "preview": "vite preview --mode test", 14 | "test": "echo \"no test specified,work in process\"", 15 | "test:coverage": "echo \"no test specified,work in process\"", 16 | "lint": "eslint ./src --ext ts,tsx", 17 | "lint:fix": "eslint ./src --ext ts,tsx --fix", 18 | "prepare": "husky install" 19 | }, 20 | "devDependencies": { 21 | "@honkhonk/vite-plugin-svgr": "^1.1.0", 22 | "@types/echarts": "^4.9.13", 23 | "@types/lodash": "^4.14.178", 24 | "@types/mockjs": "^1.0.6", 25 | "@types/node": "^20.2.5", 26 | "@types/qrcode.react": "^1.0.2", 27 | "@types/react": "^18.2.0", 28 | "@types/react-dom": "^18.2.0", 29 | "@types/react-router-dom": "^5.3.3", 30 | "@vitejs/plugin-react": "^1.3.2", 31 | "eslint": "^8.3.0", 32 | "eslint-config-airbnb-base": "^15.0.0", 33 | "eslint-config-prettier": "^8.4.0", 34 | "eslint-config-react-app": "^7.0.0", 35 | "eslint-plugin-import": "^2.25.4", 36 | "eslint-plugin-prettier": "^4.0.0", 37 | "eslint-plugin-react": "^7.28.0", 38 | "husky": "^8.0.1", 39 | "less": "^4.1.3", 40 | "prettier": "^2.5.1", 41 | "typescript": "^4.8.4", 42 | "vite": "^2.9.15", 43 | "vite-plugin-mock": "^2.9.6" 44 | }, 45 | "dependencies": { 46 | "@reduxjs/toolkit": "^1.8.5", 47 | "axios": "^1.2.0", 48 | "axios-jsonp": "^1.0.4", 49 | "classnames": "^2.3.1", 50 | "dayjs": "^1.10.7", 51 | "echarts": "^5.3.0", 52 | "echarts-for-react": "^3.0.2", 53 | "lodash": "^4.17.21", 54 | "mockjs": "^1.1.0", 55 | "qrcode.react": "^3.1.0", 56 | "react": "^18.2.0", 57 | "react-dom": "^18.2.0", 58 | "react-redux": "^7.2.4", 59 | "react-router-dom": "^6.3.0", 60 | "tdesign-icons-react": "^0.4.3", 61 | "tdesign-react": "^1.10.4", 62 | "tvision-color": "^1.5.0" 63 | }, 64 | "browserslist": { 65 | "production": [ 66 | ">0.2%", 67 | "not dead", 68 | "not op_mini all" 69 | ], 70 | "development": [ 71 | "last 1 chrome version", 72 | "last 1 firefox version", 73 | "last 1 safari version" 74 | ] 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/tdesign-react-starter/4a70384d5af80843b135d3e8bd8b1f0be34a779f/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/assets/image/assets-login-bg-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/tdesign-react-starter/4a70384d5af80843b135d3e8bd8b1f0be34a779f/src/assets/image/assets-login-bg-black.png -------------------------------------------------------------------------------- /src/assets/image/assets-login-bg-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tencent/tdesign-react-starter/4a70384d5af80843b135d3e8bd8b1f0be34a779f/src/assets/image/assets-login-bg-white.png -------------------------------------------------------------------------------- /src/assets/svg/assets-product-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/svg/assets-product-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/svg/assets-product-3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/svg/assets-product-4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/svg/assets-result-403.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/assets/svg/assets-result-404.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 33 | 36 | -------------------------------------------------------------------------------- /src/assets/svg/assets-result-500.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 19 | 20 | 21 | 22 | 23 | 26 | 29 | 32 | -------------------------------------------------------------------------------- /src/assets/svg/assets-result-network-error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /src/assets/svg/assets-setting-auto.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/svg/assets-setting-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/svg/assets-setting-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/svg/assets-t-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/components/Board/index.module.less: -------------------------------------------------------------------------------- 1 | .boardPanelDark { 2 | background: var(--td-brand-color) !important; 3 | .boardTitle, 4 | .boardItemLeft, 5 | .boardItemDesc, 6 | .trendColorUp, 7 | .trendColorDown, 8 | .boardItemBottom { 9 | color: var(--td-text-color-anti); 10 | } 11 | .trendIconUp, 12 | .trendIconDown { 13 | background: var(--td-brand-color-5); 14 | } 15 | } 16 | .boardPanel { 17 | :global { 18 | .t-card__body { 19 | padding-top: 0; 20 | } 21 | } 22 | } 23 | .boardTitle { 24 | line-height: 22px; 25 | font-size: 14px; 26 | color: var(--td-text-color-secondary); 27 | } 28 | 29 | .boardItem { 30 | display: flex; 31 | justify-content: space-between; 32 | align-items: center; 33 | } 34 | 35 | .boardItemLeft { 36 | display: inline-block; 37 | color: var(--td-text-color-primary); 38 | font-size: 27px; 39 | line-height: 44px; 40 | } 41 | 42 | .boardItemBottom { 43 | display: flex; 44 | justify-content: space-between; 45 | align-items: center; 46 | } 47 | 48 | .boardItemIcon { 49 | opacity: 0.6; 50 | } 51 | 52 | .boardItemDesc { 53 | display: flex; 54 | align-items: center; 55 | justify-content: center; 56 | line-height: 22px; 57 | color: var(--td-text-color-placeholder); 58 | } 59 | 60 | .trendIcon { 61 | border-radius: 50%; 62 | width: 16px; 63 | height: 16px; 64 | margin-left: 8px; 65 | margin-right: 8px; 66 | } 67 | 68 | .trendIconUp { 69 | background: var(--td-error-color-2); 70 | } 71 | 72 | .trendIconDown { 73 | background: var(--td-success-color-2); 74 | } 75 | 76 | .trendColorUp { 77 | color: #e34d59; 78 | display: flex; 79 | align-items: center; 80 | } 81 | 82 | .trendColorDown { 83 | color: #00a870; 84 | display: flex; 85 | align-items: center; 86 | } 87 | -------------------------------------------------------------------------------- /src/components/Board/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ChevronRightIcon } from 'tdesign-icons-react'; 3 | import { Card } from 'tdesign-react'; 4 | import classnames from 'classnames'; 5 | import Style from './index.module.less'; 6 | 7 | export enum ETrend { 8 | up, 9 | down, 10 | } 11 | 12 | export interface IBoardProps extends React.HTMLAttributes { 13 | title?: string; 14 | count?: string; 15 | Icon?: React.ReactElement; 16 | desc?: string; 17 | trend?: ETrend; 18 | trendNum?: string; 19 | dark?: boolean; 20 | border?: boolean; 21 | } 22 | 23 | export const TrendIcon = ({ trend, trendNum }: { trend?: ETrend; trendNum?: string | number }) => ( 24 |
30 |
36 | {trend === ETrend.up ? ( 37 | 38 | 39 | 40 | 41 | ) : ( 42 | 43 | 44 | 45 | 46 | )} 47 |
48 | {trendNum} 49 |
50 | ); 51 | 52 | const Board = ({ title, count, desc, trend, trendNum, Icon, dark, border = false }: IBoardProps) => ( 53 | {title}} 55 | className={classnames({ 56 | [Style.boardPanelDark]: dark, 57 | [Style.boardPanel]: true, 58 | })} 59 | bordered={border} 60 | footer={ 61 |
62 |
63 | {desc} 64 | 65 |
66 | 67 |
68 | } 69 | > 70 |
71 |
{count}
72 |
{Icon}
73 |
74 |
75 | ); 76 | 77 | export default React.memo(Board); 78 | -------------------------------------------------------------------------------- /src/components/DatePicker/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DateRangePicker, DateRangeValue } from 'tdesign-react'; 3 | import dayjs from 'dayjs'; 4 | 5 | const RECENT_7_DAYS: DateRangeValue = [ 6 | dayjs().subtract(7, 'day').format('YYYY-MM-DD'), 7 | dayjs().subtract(1, 'day').format('YYYY-MM-DD'), 8 | ]; 9 | 10 | const LastWeekDatePicker = (onChange: (value: DateRangeValue) => void) => ( 11 | onChange(value)} 17 | /> 18 | ); 19 | 20 | export default LastWeekDatePicker; 21 | -------------------------------------------------------------------------------- /src/components/ErrorPage/index.module.less: -------------------------------------------------------------------------------- 1 | .errorBox { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | height: 75vh; 7 | padding: 24px; 8 | min-height: 400px; 9 | color: var(--td-brand-color); 10 | img { 11 | width: 200px; 12 | height: 140px; 13 | color: var(--td-brand-color); 14 | } 15 | 16 | .title { 17 | font-weight: 500; 18 | font-size: 20px; 19 | line-height: 28px; 20 | margin-top: 8px; 21 | color: var(--td-text-color-primary); 22 | } 23 | .description { 24 | margin: 8px 0 32px; 25 | font-size: 14px; 26 | line-height: 22px; 27 | color: var(--td-text-color-secondary); 28 | } 29 | 30 | .rightButton { 31 | margin-left: 8px; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/components/ErrorPage/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { Button } from 'tdesign-react'; 3 | 4 | import Light403Icon from 'assets/svg/assets-result-403.svg?component'; 5 | import Light404Icon from 'assets/svg/assets-result-404.svg?component'; 6 | import Light500Icon from 'assets/svg/assets-result-500.svg?component'; 7 | import style from './index.module.less'; 8 | 9 | enum ECode { 10 | forbidden = 403, 11 | notFount = 404, 12 | error = 500, 13 | } 14 | 15 | interface IErrorPageProps { 16 | code: ECode; 17 | title?: string; 18 | desc?: string; 19 | } 20 | 21 | const errorInfo = { 22 | [ECode.forbidden]: { 23 | title: '403 Forbidden', 24 | desc: '抱歉,您无权限访问此页面', 25 | icon: , 26 | }, 27 | [ECode.notFount]: { 28 | title: '404 Not Found', 29 | desc: '抱歉,您访问的页面不存在。', 30 | icon: , 31 | }, 32 | [ECode.error]: { 33 | title: '500 Internal Server Error', 34 | desc: '抱歉,服务器出错啦!', 35 | icon: , 36 | }, 37 | }; 38 | 39 | const ErrorPage: React.FC = (props) => { 40 | const info = errorInfo[props.code]; 41 | return ( 42 |
43 | {info?.icon} 44 |
{info?.title}
45 |
{info?.desc}
46 | 47 |
48 | ); 49 | }; 50 | 51 | export default memo(ErrorPage); 52 | -------------------------------------------------------------------------------- /src/configs/color.ts: -------------------------------------------------------------------------------- 1 | import { ETheme } from 'types/index.d'; 2 | 3 | export const defaultColor = ['#0052d9', '#0594fa', '#00a870', '#ebb105', '#ed7b2f', '#e34d59', '#ed49b4', '#834ec2']; 4 | 5 | export const darkColor = ['#4582e6', '#29a4fb', '#03a56f', '#ca8d03', '#ed7b2f', '#ea7b84', '#f172c5', '#ab87d5']; 6 | 7 | export const CHART_COLORS = { 8 | [ETheme.light]: { 9 | textColor: 'rgba(0, 0, 0, 0.9)', 10 | placeholderColor: 'rgba(0, 0, 0, 0.35)', 11 | borderColor: '#dcdcdc', 12 | containerColor: '#fff', 13 | }, 14 | [ETheme.dark]: { 15 | textColor: 'rgba(255, 255, 255, 0.9)', 16 | placeholderColor: 'rgba(255, 255, 255, 0.35)', 17 | borderColor: '#5e5e5e', 18 | containerColor: '#242424', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /src/configs/host.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | mock: { 3 | // 本地mock数据 4 | API: '', 5 | }, 6 | development: { 7 | // 开发环境接口请求 8 | API: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com', 9 | }, 10 | test: { 11 | // 测试环境接口地址 12 | API: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com', 13 | }, 14 | release: { 15 | // 正式环境接口地址 16 | API: 'https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com', 17 | }, 18 | site: { 19 | // TDesign部署特殊需要 与release功能一致 20 | API: 'https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com', 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.avif' { 2 | export default src as string; 3 | } 4 | 5 | declare module '*.bmp' { 6 | export default src as string; 7 | } 8 | 9 | declare module '*.gif' { 10 | export default src as string; 11 | } 12 | 13 | declare module '*.jpg' { 14 | export default src as string; 15 | } 16 | 17 | declare module '*.jpeg' { 18 | export default src as string; 19 | } 20 | 21 | declare module '*.png' { 22 | export default src as string; 23 | } 24 | 25 | declare module '*.webp' { 26 | export default src as string; 27 | } 28 | 29 | declare module '*.svg' { 30 | export default src as string; 31 | } 32 | declare module '*.svg?component' { 33 | export default src as string; 34 | } 35 | declare module '*.module.css' { 36 | export default classes as { readonly [key: string]: string }; 37 | } 38 | 39 | declare module '*.module.less' { 40 | export default classes as { readonly [key: string]: string }; 41 | } 42 | 43 | declare module '*.less' { 44 | export default classes as { readonly [key: string]: string }; 45 | } 46 | 47 | declare module 'tvision-color'; 48 | 49 | declare interface ImportMeta { 50 | env: { 51 | MODE: 'development' | 'test' | 'release' | 'mock' | 'site'; 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /src/hooks/useDynamicChart.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | import { useAppSelector } from 'modules/store'; 3 | import { selectGlobal } from 'modules/global'; 4 | import { getChartColor } from 'utils/color'; 5 | import { CHART_COLORS } from 'configs/color'; 6 | import lodashSet from 'lodash/set'; 7 | import lodashMap from 'lodash/map'; 8 | import { ETheme } from '../types'; 9 | 10 | export type TChartColorKey = keyof (typeof CHART_COLORS)[ETheme.light]; 11 | /** 12 | * 根据当前主题色返回动态的图表颜色列表 13 | * @param options 图表的固定配置 14 | * @param configs 需要动态变换颜色的字段 15 | * @returns string[] 16 | */ 17 | export default function useDynamicChart( 18 | options: Record, 19 | configs?: Partial>>, 20 | ) { 21 | const { theme, color } = useAppSelector(selectGlobal); 22 | return useMemo(() => { 23 | const dynamicColor = getChartColor(theme, color); 24 | const newOptions = { 25 | ...options, 26 | }; 27 | // 设置动态的图表颜色 28 | lodashSet(newOptions, 'color', dynamicColor.colorList); 29 | if (configs) { 30 | lodashMap(configs, (config, configKey: TChartColorKey) => { 31 | config?.map((val) => lodashSet(newOptions, val, dynamicColor[configKey])); 32 | }); 33 | } 34 | return newOptions; 35 | }, [theme, color, options]); 36 | } 37 | -------------------------------------------------------------------------------- /src/layouts/components/AppLayout.module.less: -------------------------------------------------------------------------------- 1 | .sidePanel { 2 | height: 100%; 3 | display: flex; 4 | flex-direction: row!important; 5 | } 6 | 7 | .sideContainer { 8 | flex: 1; 9 | min-width: 760px; 10 | overflow: auto; 11 | } 12 | 13 | .topPanel { 14 | min-width: 1150px; 15 | } 16 | 17 | .mixPanel { 18 | height: 100%; 19 | } 20 | 21 | .mixMain { 22 | flex-direction: row!important; 23 | flex: 1; 24 | overflow: auto; 25 | } 26 | 27 | .mixContent { 28 | overflow: auto; 29 | } 30 | -------------------------------------------------------------------------------- /src/layouts/components/AppLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Layout } from 'tdesign-react'; 3 | import { ELayout } from 'modules/global'; 4 | import Header from './Header'; 5 | import Footer from './Footer'; 6 | import Menu from './Menu'; 7 | import classnames from 'classnames'; 8 | import Content from './AppRouter'; 9 | 10 | import Style from './AppLayout.module.less'; 11 | 12 | const SideLayout = React.memo(() => ( 13 | 14 | 15 | 16 |
17 | 18 |