commit 2284534e062d51809403706c4ec2bb0dc8c4706a
Author: 榆钱落尽槿花稀 <2675540038@qq.com>
Date: Thu Apr 18 13:44:38 2024 +0800
1
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..4fc13c7
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+root = true
+
+[*]
+indent_style = space
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{ts,js,vue,css}]
+indent_size = 2
diff --git a/.env b/.env
new file mode 100644
index 0000000..1b6a998
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+# 打包路径 根据项目不同按需配置
+VITE_BASE_URL = /
\ No newline at end of file
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000..79debef
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,2 @@
+# 打包路径
+VITE_BASE_URL = /
diff --git a/.env.site b/.env.site
new file mode 100644
index 0000000..753a6ae
--- /dev/null
+++ b/.env.site
@@ -0,0 +1,2 @@
+# 打包路径 根据项目不同按需配置
+VITE_BASE_URL = https://static.tdesign.tencent.com/starter/vue/
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..d631784
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,3 @@
+dist
+node_modules
+!.prettierrc.js
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..875ec75
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,76 @@
+{
+ "extends": ["airbnb-base", "prettier", "plugin:@typescript-eslint/recommended", "plugin:vue/essential"],
+ "env": {
+ "browser": true,
+ "node": true,
+ "jest": true,
+ "es6": true
+ },
+ "globals": {
+ "cy": "readonly"
+ },
+ "plugins": ["vue", "@typescript-eslint"],
+ "parserOptions": {
+ "parser": "@typescript-eslint/parser",
+ "sourceType": "module",
+ "allowImportExportEverywhere": true,
+ "ecmaFeatures": {
+ "jsx": true
+ }
+ },
+ "rules": {
+ "@typescript-eslint/ban-ts-ignore": 0,
+ "@typescript-eslint/no-explicit-any": 0,
+ "@typescript-eslint/no-require-imports": 0,
+ "@typescript-eslint/no-var-requires": 0,
+ "@typescript-eslint/prefer-for-of": 0,
+ "@typescript-eslint/explicit-function-return-type": 0,
+ "@typescript-eslint/explicit-module-boundary-types": 0,
+ "import/no-extraneous-dependencies": 0,
+ "import/extensions": 0,
+ "import/no-unresolved": 0,
+ "indent": [2, 2],
+ "camelcase": 0,
+ "class-methods-use-this": 0,
+ "new-cap": 0,
+ "no-new": 1,
+ "no-shadow": 0,
+ "no-console": 0,
+ "no-underscore-dangle": 0,
+ "no-confusing-arrow": 0,
+ "no-plusplus": [
+ "error",
+ {
+ "allowForLoopAfterthoughts": true
+ }
+ ],
+ "no-param-reassign": 0,
+ "func-style": 0,
+ "prefer-default-export": 0,
+ "max-len": 0,
+ "consistent-return": 0
+ },
+ "overrides": [
+ {
+ "files": ["*.vue"],
+ "rules": {
+ "vue/return-in-computed-property": 1,
+ "vue/order-in-components": 2,
+ "vue/component-name-in-template-casing": [2, "kebab-case"],
+ "vue/require-default-prop": 0,
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "import/order": "off"
+ }
+ },
+ {
+ "files": ["src/*", "*.js"],
+ "rules": {
+ "no-var-requires": 0,
+ "no-console": 0,
+ "no-unused-expressions": 0,
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "import/order": "off"
+ }
+ }
+ ]
+}
diff --git a/.github/ISSUE_TEMPLATE/bug-report.zh-CN.yml b/.github/ISSUE_TEMPLATE/bug-report.zh-CN.yml
new file mode 100644
index 0000000..feb3fc9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.zh-CN.yml
@@ -0,0 +1,79 @@
+name: 反馈 Bug
+description: 通过 github 模板进行 Bug 反馈。
+title: "[组件名称] 描述问题的标题"
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # 欢迎你的参与
+ tdesign-vue-starter 的 Issue 列表接受 bug 报告或是新功能请求。也可加入官方社区:
+
+ 在发布一个 Issue 前,请确保:
+ - 在 [常见问题](https://tdesign.tencent.com/about/faq)、[更新日志](https://tdesign.tencent.com/about/release) 和 [旧Issue列表](https://github.com/Tencent/tdesign-vue-starter/issues?q=is%3Aissue) 中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正)
+ - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。
+
+ - type: input
+ id: version
+ attributes:
+ label: tdesign-vue-starter 版本
+ description: 请检查在最新项目版本中能否重现此 issue。
+ placeholder: 请填写
+ validations:
+ required: true
+
+ - type: input
+ id: reproduce
+ attributes:
+ label: 重现链接
+ description: 请提供尽可能精简的 CodePen、CodeSandbox 或 GitHub 仓库的链接。请不要填无关链接,否则你的 Issue 将被关闭。
+ placeholder: 请填写
+
+ - type: textarea
+ id: reproduceSteps
+ attributes:
+ label: 重现步骤
+ description: 请清晰的描述重现该 Issue 的步骤,这能帮助我们快速定位问题。没有清晰重现步骤将不会被修复,标有 'need reproduction' 的 Issue 在 7 天内不提供相关步骤,将被关闭。
+ placeholder: 请填写
+
+ - type: textarea
+ id: expect
+ attributes:
+ label: 期望结果
+ placeholder: 请填写
+
+ - type: textarea
+ id: actual
+ attributes:
+ label: 实际结果
+ placeholder: 请填写
+
+ - type: input
+ id: frameworkVersion
+ attributes:
+ label: 框架版本
+ placeholder: Vue(3.2.0)
+
+ - type: input
+ id: browsersVersion
+ attributes:
+ label: 浏览器版本
+ placeholder: Chrome(8.213.231.123)
+
+ - type: input
+ id: systemVersion
+ attributes:
+ label: 系统版本
+ placeholder: MacOS(11.2.3)
+
+ - type: input
+ id: nodeVersion
+ attributes:
+ label: Node版本
+ placeholder: 请填写
+
+ - type: textarea
+ id: remarks
+ attributes:
+ label: 补充说明
+ description: 可以是遇到这个 bug 的业务场景、上下文等信息。
+ placeholder: 请填写
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..1e82356
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: true
+contact_links:
+ - name: 使用 issue-helper 新建
+ url: https://Tencent.github.io/tdesign/issue-helper/?lang=zh-CN&repo=Tencent/tdesign-vue-starter
+ about: 使用 https://Tencent.github.io/tdesign/issue-helper/ 创建 issue,其中包含 bug 和 feature,表单提交更加严格。
diff --git a/.github/ISSUE_TEMPLATE/feature-report.zh-CN.yml b/.github/ISSUE_TEMPLATE/feature-report.zh-CN.yml
new file mode 100644
index 0000000..f21a354
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-report.zh-CN.yml
@@ -0,0 +1,30 @@
+name: 反馈新功能
+description: 通过 github 模板进行新功能反馈。
+title: "[组件名称] 描述问题的标题"
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # 欢迎你的参与
+ tdesign-vue-starter 的 Issue 列表接受 bug 报告或是新功能请求。也可加入官方社区:
+
+ 在发布一个 Issue 前,请确保:
+ - 在 [常见问题](https://tdesign.tencent.com/about/faq)、[更新日志](https://tdesign.tencent.com/about/release) 和 [旧Issue列表](https://github.com/Tencent/tdesign-vue-starter/issues?q=is%3Aissue) 中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正)
+ - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。
+
+ - type: textarea
+ id: functionContent
+ attributes:
+ label: 这个功能解决了什么问题
+ description: 请详尽说明这个需求的用例和场景。最重要的是:解释清楚是怎样的用户体验需求催生了这个功能上的需求。我们将考虑添加在现有 API 无法轻松实现的功能。新功能的用例也应当足够常见。
+ placeholder: 请填写
+ validations:
+ required: true
+
+ - type: textarea
+ id: functionalExpectations
+ attributes:
+ label: 你建议的方案是什么
+ placeholder: 请填写
+ validations:
+ required: true
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..a97d15e
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,52 @@
+
+
+### 🤔 这个 PR 的性质是?
+
+- [ ] 日常 bug 修复
+- [ ] 新特性提交
+- [ ] 文档改进
+- [ ] 演示代码改进
+- [ ] 组件样式/交互改进
+- [ ] CI/CD 改进
+- [ ] 重构
+- [ ] 代码风格优化
+- [ ] 测试用例
+- [ ] 分支合并
+- [ ] 其他
+
+### 🔗 相关 Issue
+
+
+
+### 💡 需求背景和解决方案
+
+
+
+### 📝 更新日志
+
+
+
+- fix(组件名称): 处理问题或特性描述 ...
+
+- [ ] 本条 PR 不需要纳入 Changelog
+
+### ☑️ 请求合并前的自查清单
+
+⚠️ 请自检并全部**勾选全部选项**。⚠️
+
+- [ ] 文档已补充或无须补充
+- [ ] 代码演示已提供或无须提供
+- [ ] TypeScript 定义已补充或无须补充
+- [ ] Changelog 已提供或无须提供
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..c37a937
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,20 @@
+# Basic dependabot.yml file with
+# minimum configuration for two package managers
+
+version: 2
+updates:
+ # Enable version updates for npm
+ - package-ecosystem: "npm"
+ # Look for `package.json` and `lock` files in the `root` directory
+ directory: "/"
+ # Check the npm registry for updates every day (weekdays)
+ schedule:
+ interval: "monthly"
+
+ # Enable version updates for Docker
+ - package-ecosystem: "docker"
+ # Look for a `Dockerfile` in the `root` directory
+ directory: "/"
+ # Check for updates once a week
+ schedule:
+ interval: "monthly"
diff --git a/.github/workflows/issue-assignees.temp.yml b/.github/workflows/issue-assignees.temp.yml
new file mode 100644
index 0000000..83d5d6b
--- /dev/null
+++ b/.github/workflows/issue-assignees.temp.yml
@@ -0,0 +1,52 @@
+# force copy from tencent/tdesign
+name: Issue Add Assigness
+
+on:
+ issues:
+ types: [opened, edited]
+
+jobs:
+ mark-duplicate:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: wow-actions/auto-comment@v1
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ issuesOpened: |
+ 👋 @{{ author }},感谢给 TDesign 提出了 issue。
+ 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。
+
+ # https://docs.github.com/cn/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues
+ - uses: 94dreamer/issue-assignees@main
+ id: assignees
+ with:
+ project_name: ${{github.event.repository.name}}
+ issue_title: ${{github.event.issue.title}}
+
+ - run: echo ${{ steps.assignees.outputs.contributors }}
+ - name: Add assigness
+ if: steps.assignees.outputs.contributors != ''
+ uses: actions-cool/issues-helper@v3
+ with:
+ actions: 'add-assignees'
+ token: ${{ secrets.GITHUB_TOKEN }}
+ issue-number: ${{ github.event.issue.number }}
+ assignees: ${{ steps.assignees.outputs.contributors }}
+
+ - run: |
+ contributors=${{ steps.assignees.outputs.contributors }}
+ contributorstring=${contributors//,/ @}
+ echo "::set-output name=string::@$contributorstring"
+ id: contributors
+
+ - name: 通知贡献者
+ if: steps.assignees.outputs.contributors != ''
+ uses: actions-cool/maintain-one-comment@v2.0.0
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ body: |
+ ♥️ 有劳 ${{ steps.contributors.outputs.string }} 尽快确认问题。
+ 确认有效后将下一步计划和可能需要的时间回复给 @${{ github.event.issue.user.login }} 。
+
+ number: ${{ github.event.issue.number }}
+ body-include: ""
diff --git a/.github/workflows/issue-help-wanted.temp.yml b/.github/workflows/issue-help-wanted.temp.yml
new file mode 100644
index 0000000..94e9bbd
--- /dev/null
+++ b/.github/workflows/issue-help-wanted.temp.yml
@@ -0,0 +1,22 @@
+# force copy from tencent/tdesign
+name: Issue Help wanted
+on:
+ issues:
+ types:
+ - labeled
+jobs:
+ add-comment:
+ if: github.event.label.name == 'help wanted'
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ steps:
+ - name: Add comment
+ uses: peter-evans/create-or-update-comment@v1
+ with:
+ issue-number: ${{ github.event.issue.number }}
+ body: |
+ 任何人都可以处理此问题。
+ **请务必在您的 `pull request` 中引用此问题。** :sparkles:
+ 感谢你的贡献! :sparkles:
+ reactions: heart
\ No newline at end of file
diff --git a/.github/workflows/issue-mark-duplicate.temp.yml b/.github/workflows/issue-mark-duplicate.temp.yml
new file mode 100644
index 0000000..3017723
--- /dev/null
+++ b/.github/workflows/issue-mark-duplicate.temp.yml
@@ -0,0 +1,19 @@
+# force copy from tencent/tdesign
+# 当在 issue 的 comment 回复类似 `Duplicate of #111` 这样的话,issue 将被自动打上 重复提交标签 并且 cloese
+name: Issue Mark Duplicate
+
+on:
+ issue_comment:
+ types: [created, edited]
+
+jobs:
+ mark-duplicate:
+ runs-on: ubuntu-latest
+ steps:
+ - name: mark-duplicate
+ uses: actions-cool/issues-helper@v2
+ with:
+ actions: "mark-duplicate"
+ token: ${{ secrets.GITHUB_TOKEN }}
+ duplicate-labels: "duplicate"
+ close-issue: true
diff --git a/.github/workflows/issue-reply.temp.yml b/.github/workflows/issue-reply.temp.yml
new file mode 100644
index 0000000..271a94f
--- /dev/null
+++ b/.github/workflows/issue-reply.temp.yml
@@ -0,0 +1,21 @@
+# force copy from tencent/tdesign
+# 当被打上 Need Reproduce 标签时候,自动提示需要重现实例
+
+name: ISSUE_REPLY
+
+on:
+ issues:
+ types: [labeled]
+
+jobs:
+ issue-reply:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Need Reproduce
+ if: github.event.label.name == 'Need Reproduce'
+ uses: actions-cool/issues-helper@v2
+ with:
+ actions: 'create-comment'
+ issue-number: ${{ github.event.issue.number }}
+ body: |
+ 你好 @${{ github.event.issue.user.login }}, 我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击 [此处](https://codesandbox.io/) 创建一个 codesandbox 或者提供一个最小化的 GitHub 仓库。请确保选择准确的版本。
diff --git a/.github/workflows/issue-synchronize.temp.yml b/.github/workflows/issue-synchronize.temp.yml
new file mode 100644
index 0000000..4ca7de1
--- /dev/null
+++ b/.github/workflows/issue-synchronize.temp.yml
@@ -0,0 +1,17 @@
+# force copy from tencent/tdesign
+name: Issue Add Assigness
+
+on:
+ issues:
+ types: [opened, reopened]
+
+jobs:
+ mark-duplicate:
+ runs-on: ubuntu-latest
+ steps:
+ # https://docs.github.com/cn/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues
+ - uses: 94dreamer/create-report@main
+ with:
+ wxhook: ${{ secrets.WX_HOOK_URL }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ type: 'issue'
\ No newline at end of file
diff --git a/.github/workflows/pr-spelling.temp.yml b/.github/workflows/pr-spelling.temp.yml
new file mode 100644
index 0000000..93e138e
--- /dev/null
+++ b/.github/workflows/pr-spelling.temp.yml
@@ -0,0 +1,12 @@
+# force copy from tencent/tdesign
+name: pr-spell-check
+on: [pull_request]
+
+jobs:
+ run:
+ name: Spell Check with Typos
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Check spelling
+ uses: crate-ci/typos@master
diff --git a/.github/workflows/preview-publish.yml b/.github/workflows/preview-publish.yml
new file mode 100644
index 0000000..364f99c
--- /dev/null
+++ b/.github/workflows/preview-publish.yml
@@ -0,0 +1,15 @@
+# 文件名建议统一为 preview-publish
+# 应用 preview.yml 的 demo
+name: PREVIEW_PUBLISH
+
+on:
+ workflow_run:
+ workflows: ["MAIN_PULL_REQUEST"]
+ types:
+ - completed
+
+jobs:
+ call-preview:
+ uses: Tencent/tdesign/.github/workflows/preview.yml@main
+ secrets:
+ TDESIGN_SURGE_TOKEN: ${{ secrets.TDESIGN_SURGE_TOKEN }}
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
new file mode 100644
index 0000000..280a82f
--- /dev/null
+++ b/.github/workflows/pull-request.yml
@@ -0,0 +1,14 @@
+# 文件名建议统一为 pull-request.yml
+# 应用 test-build.yml 的 demo
+
+name: MAIN_PULL_REQUEST
+
+on:
+ pull_request:
+ branches: [develop, main, site]
+ types: [opened, synchronize, reopened]
+
+jobs:
+ call-test-build:
+ uses: Tencent/tdesign/.github/workflows/test-build.yml@main
+# install lint
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2c4cd52
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+*.local
+.vscode
+.history
+README.html
+
+.stylelintcache
+.idea
+yarn.lock
+package-lock.json
\ No newline at end of file
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100644
index 0000000..ccfec39
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx --no-install commitlint -e $GIT_PARAMS
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..c37466e
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx lint-staged
\ No newline at end of file
diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg
new file mode 100644
index 0000000..71fe5b3
--- /dev/null
+++ b/.husky/prepare-commit-msg
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+exec < /dev/tty && npx git-cz --hook || true
\ No newline at end of file
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..5e92232
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,39 @@
+module.exports = {
+ // 一行最多 120 字符
+ printWidth: 120,
+ // 使用 2 个空格缩进
+ tabWidth: 2,
+ // 不使用缩进符,而使用空格
+ useTabs: false,
+ // 行尾需要有分号
+ semi: true,
+ // 使用单引号
+ singleQuote: true,
+ // 对象的 key 仅在必要时用引号
+ quoteProps: 'as-needed',
+ // jsx 不使用单引号,而使用双引号
+ jsxSingleQuote: false,
+ // 末尾需要有逗号
+ trailingComma: 'all',
+ // 大括号内的首尾需要空格
+ bracketSpacing: true,
+ // jsx 标签的反尖括号需要换行
+ jsxBracketSameLine: false,
+ // 箭头函数,只有一个参数的时候,也需要括号
+ arrowParens: 'always',
+ // 每个文件格式化的范围是文件的全部内容
+ rangeStart: 0,
+ rangeEnd: Infinity,
+ // 不需要写文件开头的 @prettier
+ requirePragma: false,
+ // 不需要自动在文件开头插入 @prettier
+ insertPragma: false,
+ // 使用默认的折行标准
+ proseWrap: 'preserve',
+ // 根据显示样式决定 html 要不要折行
+ htmlWhitespaceSensitivity: 'css',
+ // vue 文件中的 script 和 style 内不用缩进
+ vueIndentScriptAndStyle: false,
+ // 换行符使用 lf
+ endOfLine: 'lf',
+};
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 0000000..1b7da3c
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,8 @@
+# .stylelintignore
+# 旧的不需打包的样式库
+*.min.css
+
+# 其他类型文件
+*.js
+*.jpg
+*.woff
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..789cbde
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) 2021-present TDesign
+
+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:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+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.
diff --git a/PROXY.md b/PROXY.md
new file mode 100644
index 0000000..8a56932
--- /dev/null
+++ b/PROXY.md
@@ -0,0 +1,22 @@
+# TDesign starter 本地开发联调
+
+## 工具准备
+
+- 浏览器插件:[SwitchyOmega](https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=zh-CNhttps://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=zh-CN)
+- 调试代理工具:[whistle](https://wproxy.org/whistle/)
+
+## 代理配置
+
+`npm run dev`开启本地服务后,可以配置代理将线上域名的非后台 api 路径(如`/api`)的静态文件请求代理到本地,这样就可以进行本地联调和前端代码热更新了。
+
+举例子:
+
+```
+/tdesign.tencent.com(?!\/api)/ 127.0.0.1:3001
+```
+
+其中:
+
+- tdesign.tencent.com:修改你的线上域名
+- /api:修改成后台请求路径
+- 3001:修改成本地服务端口
diff --git a/README-zh_CN.md b/README-zh_CN.md
new file mode 100644
index 0000000..cb90038
--- /dev/null
+++ b/README-zh_CN.md
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+简体中文 | [English](./README.md)
+
+### 项目简介
+
+TDesign Vue Starter 是一个基于 tdesign-vue,使用 `Vue2`、`Vite`开发,可进行个性化主题配置,旨在提供项目开箱即用的、配置式的中后台项目。
+
+
+ 在线预览
+ ·
+ 使用文档
+
+
+
+
+
+### 特性
+
+- 内置多种常用的中后台页面
+- 完善的目录结构
+- 完善的代码规范配置
+- 支持暗黑模式
+- 自定义主题颜色
+- 多种空间布局
+- 内置 Mock 数据方案
+
+### 使用
+
+> 通过 [tdesign-starter-cli](https://www.npmjs.com/package/tdesign-starter-cli) 初始化项目仓库
+
+```bash
+## 1、安装 tdesign-starter-cli
+npm i tdesign-starter-cli@latest -g
+
+## 2、创建项目
+td-starter init
+```
+
+### 开发
+
+```bash
+## 安装依赖
+npm install
+
+## 启动项目
+npm run dev
+```
+
+### 构建
+
+```bash
+## 构建正式环境
+npm run build
+
+## 构建测试环境
+npm run build:test
+```
+
+### 其他
+
+```bash
+## 预览构建产物
+npm run preview
+
+## 代码格式检查
+npm run lint
+
+## 代码格式检查与自动修复
+npm run lint:fix
+
+## style格式检查
+npm run stylelint
+
+## style格式检查与自动修复
+npm run stylelint:fix
+```
+
+### 如何贡献
+
+非常欢迎您的贡献!提交您的 [Issue](https://github.com/tencent/tdesign-vue-starter/issues/new/choose) 或者提交 [Pull Request](https://github.com/Tencent/tdesign-vue-starter/pulls)。
+
+#### 贡献提交规范
+
+- [Angular Convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
+- [Vue Style Guide](https://v3.vuejs.org/style-guide/#rule-categories)
+
+### 兼容性
+
+| [ ](http://godban.github.io/browsers-support-badges/) IE / Edge | [ ](http://godban.github.io/browsers-support-badges/)Firefox | [ ](http://godban.github.io/browsers-support-badges/)Chrome | [ ](http://godban.github.io/browsers-support-badges/)Safari |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
+
+### 社区版本
+
+基于 TDesign Vue 的 starter-kit 有多种社区版本,访问 [社区链接](https://tdesign.tencent.com/starter/docs/vue/community-link) 可以访问更多版本。
+如果您也开发了 TDesign Starter 的社区版本,可以提交 Issue 或者直接给我们提Pull Request 😊。
+
+### 开源协议
+
+TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-vue-starter/LICENSE)。
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4ead8fd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+English | [简体中文](./README-zh_CN.md)
+### Introduction
+
+TDesign Vue Starter is a TDesign-based project developed with `Vue2`, `Vite`. It can be customized theme configuration, and aims to provide project out-of-the-box, configuration-style middle and background projects.
+
+
+ Live Preview
+ ·
+ Documentation
+
+
+
+
+### Features
+
+- Various provided pages for develop
+- Complete directory structure for develop
+- Code specification configuration
+- Support dark mode
+- Custom theme colors
+- Various space layouts
+- Mock data scheme
+
+### Usage
+
+> Initialize project with our CLI tool `tdesign-starter-cli`
+
+```bash
+## install tdesign-starter-cli
+npm i tdesign-starter-cli@latest -g
+
+## create project
+td-starter init
+```
+
+### Develop
+
+```bash
+## install dependencies
+npm install
+
+## set up
+npm run dev
+```
+
+### Build
+
+```bash
+## build
+npm run build
+
+## build for test
+npm run build:test
+```
+
+
+### Contributing Guide
+
+We welcome contributions to our project. Create your [Issue](https://github.com/tencent/tdesign-vue-starter/issues/new/choose) or Submit your [Pull Request](https://github.com/Tencent/tdesign-vue-starter/pulls).
+
+#### Commit Specification
+
+- [Angular Convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
+- [Vue Style Guide](https://v3.vuejs.org/style-guide/#rule-categories)
+
+### Browser Support
+
+| [ ](http://godban.github.io/browsers-support-badges/) IE / Edge | [ ](http://godban.github.io/browsers-support-badges/)Firefox | [ ](http://godban.github.io/browsers-support-badges/)Chrome | [ ](http://godban.github.io/browsers-support-badges/)Safari |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
+
+### Community Versions
+
+There are kinds of community versions of starter-kit based on TDesign Vue Next, visit [community-link](https://tdesign.tencent.com/starter/docs/vue-next/community-link) for more detail. If you developed a community versions of tdesign starter, please create a issue or submit a pull request to let us know 😊.
+
+### License
+
+The MIT License. Please see [the license file](LICENSE) for more information.
diff --git a/cache.dockerfile b/cache.dockerfile
new file mode 100644
index 0000000..5e0cae1
--- /dev/null
+++ b/cache.dockerfile
@@ -0,0 +1,15 @@
+# 选择一个 Base 镜像
+FROM node:12
+
+# 设置工作目录
+WORKDIR /space
+
+# 将 by 中的文件列表 COPY 过来
+COPY . .
+
+# 根据 COPY 过来的文件进行依赖的安装
+RUN npm i
+
+# 设置好需要的环境变量
+ENV NODE_PATH=/space/node_modules
+
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 0000000..422b194
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1 @@
+module.exports = { extends: ['@commitlint/config-conventional'] };
diff --git a/globals.d.ts b/globals.d.ts
new file mode 100644
index 0000000..09a605d
--- /dev/null
+++ b/globals.d.ts
@@ -0,0 +1,13 @@
+// 通用声明
+declare type ClassName = { [className: string]: any } | ClassName[] | string;
+
+declare interface ImportMeta {
+ env: {
+ MODE: 'mock' | 'development' | 'test' | 'release' | 'site';
+ };
+}
+
+declare module '*.svg' {
+ const content: string;
+ export default content;
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..15db5e8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jsx.d.ts b/jsx.d.ts
new file mode 100644
index 0000000..84f32e2
--- /dev/null
+++ b/jsx.d.ts
@@ -0,0 +1,13 @@
+import Vue, { VNode } from 'vue';
+
+
+declare global {
+ namespace JSX {
+ type Element = VNode;
+ type ElementClass = Vue;
+ interface IntrinsicElements {
+ [elem: string]: any;
+ }
+ type IntrinsicAttributes = any;
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..03e28e0
--- /dev/null
+++ b/package.json
@@ -0,0 +1,90 @@
+{
+ "name": "yunshangxie",
+ "version": "0.6.2",
+ "scripts": {
+ "dev:mock": "vite --open --mode mock",
+ "dev": "vite --open --mode development",
+ "dev:linux": "vite --mode development",
+ "build:test": "vite build --mode test",
+ "build": "vite build --mode release",
+ "build:site": "vite build --mode site",
+ "site:preview": "npm run build && cp -r dist _site",
+ "preview": "vite preview",
+ "lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0",
+ "lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix",
+ "stylelint": "stylelint src/**/*.{html,vue,sass,less}",
+ "stylelint:fix": "stylelint --cache --fix src/**/*.{html,vue,vss,sass,less}",
+ "prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || is-ci || husky install",
+ "test": "echo \"no test specified,work in process\"",
+ "test:coverage": "echo \"no test:coverage specified,work in process\""
+ },
+ "dependencies": {
+ "@wangeditor/editor-for-vue": "^1.0.2",
+ "axios": "^1.1.3",
+ "dayjs": "^1.10.8",
+ "echarts": "5.1.2",
+ "lodash": "^4.17.21",
+ "nprogress": "^0.2.0",
+ "qrcode.vue": "^1.7.0",
+ "tdesign-icons-vue": "^0.1.11",
+ "tdesign-vue": "^1.9.0",
+ "tvision-color": "~1.6.0",
+ "typescript": "^5.1.6",
+ "vue": "~2.6.14",
+ "vue-clipboard2": "^0.3.1",
+ "vue-router": "^3.5.1",
+ "vuex": "^3.6.2",
+ "vuex-router-sync": "^5.0.0"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "^17.0.3",
+ "@commitlint/config-conventional": "^17.1.0",
+ "@types/vue-color": "^2.4.3",
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
+ "@typescript-eslint/parser": "^6.17.0",
+ "commitizen": "^4.2.3",
+ "eslint": "^7.22.0",
+ "eslint-config-airbnb-base": "^14.2.1",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-import-resolver-alias": "^1.1.2",
+ "eslint-plugin-import": "^2.22.1",
+ "eslint-plugin-vue": "^7.8.0",
+ "husky": "^8.0.1",
+ "less": "^4.1.0",
+ "lint-staged": "^13.0.3",
+ "mockjs": "^1.1.0",
+ "prettier": "^2.6.0",
+ "stylelint": "~13.13.1",
+ "stylelint-config-prettier": "~9.0.3",
+ "stylelint-less": "1.0.5",
+ "stylelint-order": "~4.1.0",
+ "vite": "^4.1.4",
+ "vite-plugin-mock": "^3.0.0",
+ "vite-plugin-theme": "^0.8.1",
+ "vite-plugin-vue2": "^2.0.1",
+ "vite-plugin-vue2-svg": "~0.4.0",
+ "vue-template-compiler": "~2.6.14"
+ },
+ "config": {
+ "commitizen": {
+ "path": "./node_modules/cz-conventional-changelog"
+ }
+ },
+ "husky": {
+ "hooks": {
+ "pre-commit": "lint-staged",
+ "prepare-commit-msg": "exec < /dev/tty && git cz --hook || true",
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
+ }
+ },
+ "lint-staged": {
+ "*.{js,jsx,vue,ts,tsx}": [
+ "prettier --write",
+ "npm run lint:fix"
+ ],
+ "*.{html,vue,vss,sass,less}": [
+ "npm run stylelint:fix"
+ ]
+ },
+ "description": "云商协"
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..086ac80
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/shims-vue.d.ts b/shims-vue.d.ts
new file mode 100644
index 0000000..5424484
--- /dev/null
+++ b/shims-vue.d.ts
@@ -0,0 +1,5 @@
+declare module '*.vue' {
+ import Vue from 'vue';
+
+ export default Vue;
+}
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..d8b29fb
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/src/assets/assets-login-bg-black.png b/src/assets/assets-login-bg-black.png
new file mode 100644
index 0000000..b4dde4b
Binary files /dev/null and b/src/assets/assets-login-bg-black.png differ
diff --git a/src/assets/assets-login-bg-white.png b/src/assets/assets-login-bg-white.png
new file mode 100644
index 0000000..4275549
Binary files /dev/null and b/src/assets/assets-login-bg-white.png differ
diff --git a/src/assets/assets-logo-full.svg b/src/assets/assets-logo-full.svg
new file mode 100644
index 0000000..94f0049
--- /dev/null
+++ b/src/assets/assets-logo-full.svg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/assets-product-1.svg b/src/assets/assets-product-1.svg
new file mode 100644
index 0000000..29e97f0
--- /dev/null
+++ b/src/assets/assets-product-1.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-product-2.svg b/src/assets/assets-product-2.svg
new file mode 100644
index 0000000..827c8bf
--- /dev/null
+++ b/src/assets/assets-product-2.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-product-3.svg b/src/assets/assets-product-3.svg
new file mode 100644
index 0000000..a3d461b
--- /dev/null
+++ b/src/assets/assets-product-3.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-product-4.svg b/src/assets/assets-product-4.svg
new file mode 100644
index 0000000..7ac1abc
--- /dev/null
+++ b/src/assets/assets-product-4.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-result-403.svg b/src/assets/assets-result-403.svg
new file mode 100644
index 0000000..343a25e
--- /dev/null
+++ b/src/assets/assets-result-403.svg
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-result-404.svg b/src/assets/assets-result-404.svg
new file mode 100644
index 0000000..db1cb36
--- /dev/null
+++ b/src/assets/assets-result-404.svg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-result-500.svg b/src/assets/assets-result-500.svg
new file mode 100644
index 0000000..e820fe2
--- /dev/null
+++ b/src/assets/assets-result-500.svg
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-result-ie.svg b/src/assets/assets-result-ie.svg
new file mode 100644
index 0000000..ebaf5ba
--- /dev/null
+++ b/src/assets/assets-result-ie.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-result-maintenance.svg b/src/assets/assets-result-maintenance.svg
new file mode 100644
index 0000000..f0cc27e
--- /dev/null
+++ b/src/assets/assets-result-maintenance.svg
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/assets-result-wifi.svg b/src/assets/assets-result-wifi.svg
new file mode 100644
index 0000000..eeee8b5
--- /dev/null
+++ b/src/assets/assets-result-wifi.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-setting-auto.svg b/src/assets/assets-setting-auto.svg
new file mode 100644
index 0000000..66f57de
--- /dev/null
+++ b/src/assets/assets-setting-auto.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-setting-dark.svg b/src/assets/assets-setting-dark.svg
new file mode 100644
index 0000000..0f15649
--- /dev/null
+++ b/src/assets/assets-setting-dark.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-setting-light.svg b/src/assets/assets-setting-light.svg
new file mode 100644
index 0000000..ffa8f34
--- /dev/null
+++ b/src/assets/assets-setting-light.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/assets-t-logo.svg b/src/assets/assets-t-logo.svg
new file mode 100644
index 0000000..3f95cba
--- /dev/null
+++ b/src/assets/assets-t-logo.svg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/assets-tencent-logo.png b/src/assets/assets-tencent-logo.png
new file mode 100644
index 0000000..26fdb92
Binary files /dev/null and b/src/assets/assets-tencent-logo.png differ
diff --git a/src/components/color/index.vue b/src/components/color/index.vue
new file mode 100644
index 0000000..cbc41d3
--- /dev/null
+++ b/src/components/color/index.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
diff --git a/src/components/product-card/index.vue b/src/components/product-card/index.vue
new file mode 100644
index 0000000..fb97173
--- /dev/null
+++ b/src/components/product-card/index.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ product.isSetup ? '已启用' : '已停用'
+ }}
+
+
+ {{ product.name }}
+ {{ product.description }}
+
+
+
+ {{ typeMap[product.type - 1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/result/index.vue b/src/components/result/index.vue
new file mode 100644
index 0000000..b730233
--- /dev/null
+++ b/src/components/result/index.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
{{ title }}
+
{{ tip }}
+
+
+
+
+
diff --git a/src/components/thumbnail/index.vue b/src/components/thumbnail/index.vue
new file mode 100644
index 0000000..61d8bac
--- /dev/null
+++ b/src/components/thumbnail/index.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/src/components/trend/index.vue b/src/components/trend/index.vue
new file mode 100644
index 0000000..2b2a7ba
--- /dev/null
+++ b/src/components/trend/index.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ describe }}
+
+
+
+
+
diff --git a/src/config/color.ts b/src/config/color.ts
new file mode 100644
index 0000000..300ac1d
--- /dev/null
+++ b/src/config/color.ts
@@ -0,0 +1,30 @@
+export type TColorToken = Record;
+export type TColorSeries = Record;
+
+// TODO: 中性色暂时固定 待tvision-color生成带色彩倾向的中性色
+export const LIGHT_CHART_COLORS = {
+ textColor: 'rgba(0, 0, 0, 0.9)',
+ placeholderColor: 'rgba(0, 0, 0, 0.35)',
+ borderColor: '#dcdcdc',
+ containerColor: '#fff',
+};
+
+export const DARK_CHART_COLORS = {
+ textColor: 'rgba(255, 255, 255, 0.9)',
+ placeholderColor: 'rgba(255, 255, 255, 0.35)',
+ borderColor: '#5e5e5e',
+ containerColor: '#242424',
+};
+
+export type TChartColor = typeof LIGHT_CHART_COLORS;
+
+export const DEFAULT_COLOR_OPTIONS = [
+ '#0052D9',
+ '#0594FA',
+ '#00A870',
+ '#EBB105',
+ '#ED7B2F',
+ '#E34D59',
+ '#ED49B4',
+ '#834EC2',
+];
diff --git a/src/config/global.ts b/src/config/global.ts
new file mode 100644
index 0000000..5ea972f
--- /dev/null
+++ b/src/config/global.ts
@@ -0,0 +1,2 @@
+export const prefix = 'tdesign-starter';
+export const TOKEN_NAME = 'tdesign-starter';
diff --git a/src/config/host.ts b/src/config/host.ts
new file mode 100644
index 0000000..b6145e2
--- /dev/null
+++ b/src/config/host.ts
@@ -0,0 +1,26 @@
+export default {
+ development: {
+ // 开发环境接口请求
+ API: '',
+ // 开发环境 cdn 路径
+ CDN: '',
+ },
+ test: {
+ // 测试环境接口地址
+ API: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com',
+ // 测试环境 cdn 路径
+ CDN: '',
+ },
+ release: {
+ // 正式环境接口地址
+ API: 'https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com',
+ // 正式环境 cdn 路径
+ CDN: '',
+ },
+ site: {
+ // 正式环境接口地址
+ API: 'https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com',
+ // 正式环境 cdn 路径
+ CDN: '',
+ },
+};
diff --git a/src/config/style.ts b/src/config/style.ts
new file mode 100644
index 0000000..b652f5a
--- /dev/null
+++ b/src/config/style.ts
@@ -0,0 +1,14 @@
+export default {
+ showFooter: true,
+ isSidebarCompact: false,
+ showBreadcrumb: false,
+ mode: 'light',
+ layout: 'side',
+ splitMenu: false,
+ isFooterAside: false,
+ isSidebarFixed: true,
+ isHeaderFixed: true,
+ isUseTabsRouter: false,
+ showHeader: true,
+ brandTheme: '#0052D9',
+};
diff --git a/src/constants/index.ts b/src/constants/index.ts
new file mode 100644
index 0000000..06557c7
--- /dev/null
+++ b/src/constants/index.ts
@@ -0,0 +1,46 @@
+interface IOption {
+ value: number | string;
+ label: string;
+}
+// 合同状态枚举
+export const CONTRACT_STATUS = {
+ FAIL: 0,
+ AUDIT_PENDING: 1,
+ EXEC_PENDING: 2,
+ EXECUTING: 3,
+ FINISH: 4,
+};
+
+export const CONTRACT_STATUS_OPTIONS: Array = [
+ { value: CONTRACT_STATUS.FAIL, label: '审核失败' },
+ { value: CONTRACT_STATUS.AUDIT_PENDING, label: '待审核' },
+ { value: CONTRACT_STATUS.EXEC_PENDING, label: '待履行' },
+ { value: CONTRACT_STATUS.EXECUTING, label: '审核成功' },
+ { value: CONTRACT_STATUS.FINISH, label: '已完成' },
+];
+
+// 合同类型枚举
+export const CONTRACT_TYPES = {
+ MAIN: 0,
+ SUB: 1,
+ SUPPLEMENT: 2,
+};
+
+export const CONTRACT_TYPE_OPTIONS: Array = [
+ { value: CONTRACT_TYPES.MAIN, label: '主合同' },
+ { value: CONTRACT_TYPES.SUB, label: '子合同' },
+ { value: CONTRACT_TYPES.SUPPLEMENT, label: '补充合同' },
+];
+
+// 合同收付类型枚举
+export const CONTRACT_PAYMENT_TYPES = {
+ PAYMENT: 0,
+ RECIPT: 1,
+};
+
+// 通知的优先级对应的TAG类型
+export const NOTIFICATION_TYPES = {
+ low: 'primary',
+ middle: 'warning',
+ high: 'danger',
+};
diff --git a/src/interface.ts b/src/interface.ts
new file mode 100644
index 0000000..f82260c
--- /dev/null
+++ b/src/interface.ts
@@ -0,0 +1,39 @@
+import STYLE_CONFIG from '@/config/style';
+
+export interface ResDataType {
+ code: number;
+ data: any;
+}
+
+export interface MenuRoute {
+ path: string;
+ title?: string;
+ icon?:
+ | string
+ | {
+ render: () => void;
+ };
+ redirect?: string;
+ children: MenuRoute[];
+ meta: any;
+}
+
+export type ModeType = 'dark' | 'light';
+
+export type SettingType = typeof STYLE_CONFIG;
+
+export type ClassName = { [className: string]: any } | ClassName[] | string;
+
+export type CommonObjType = {
+ [key: string]: string | number;
+};
+
+export interface NotificationItem {
+ id: string;
+ content: string;
+ type: string;
+ status: boolean;
+ collected: boolean;
+ date: string;
+ quality: 'high' | 'low' | 'middle';
+}
diff --git a/src/layouts/blank.vue b/src/layouts/blank.vue
new file mode 100644
index 0000000..dcdc217
--- /dev/null
+++ b/src/layouts/blank.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/src/layouts/components/Breadcrumb.vue b/src/layouts/components/Breadcrumb.vue
new file mode 100644
index 0000000..24b774d
--- /dev/null
+++ b/src/layouts/components/Breadcrumb.vue
@@ -0,0 +1,39 @@
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
diff --git a/src/layouts/components/Content.vue b/src/layouts/components/Content.vue
new file mode 100644
index 0000000..7c80189
--- /dev/null
+++ b/src/layouts/components/Content.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/Footer.vue b/src/layouts/components/Footer.vue
new file mode 100644
index 0000000..821ce66
--- /dev/null
+++ b/src/layouts/components/Footer.vue
@@ -0,0 +1,27 @@
+
+ Copyright © 2021-{{ new Date().getFullYear() }} Tencent. All Rights Reserved
+
+
+
+
+
diff --git a/src/layouts/components/Header.vue b/src/layouts/components/Header.vue
new file mode 100644
index 0000000..a271095
--- /dev/null
+++ b/src/layouts/components/Header.vue
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 个人中心
+
+
+ 退出登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/LayoutContent.vue b/src/layouts/components/LayoutContent.vue
new file mode 100644
index 0000000..d5c1e5b
--- /dev/null
+++ b/src/layouts/components/LayoutContent.vue
@@ -0,0 +1,168 @@
+
+
+
+ handleRemove(route.path, idx)"
+ >
+
+
+
+ {{ route.title }}
+
+
+
+
+ handleRefresh(route.path, idx)">
+
+ 刷新
+
+ handleCloseAhead(route.path, idx)">
+
+ 关闭左侧
+
+ handleCloseBehind(route.path, idx)"
+ >
+
+ 关闭右侧
+
+ handleCloseOther(route.path, idx)">
+
+ 关闭其它
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/LayoutHeader.vue b/src/layouts/components/LayoutHeader.vue
new file mode 100644
index 0000000..cd0c866
--- /dev/null
+++ b/src/layouts/components/LayoutHeader.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
diff --git a/src/layouts/components/LayoutSidebar.vue b/src/layouts/components/LayoutSidebar.vue
new file mode 100644
index 0000000..3e44db6
--- /dev/null
+++ b/src/layouts/components/LayoutSidebar.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
diff --git a/src/layouts/components/MenuContent.vue b/src/layouts/components/MenuContent.vue
new file mode 100644
index 0000000..b4a6f4e
--- /dev/null
+++ b/src/layouts/components/MenuContent.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/Notice.vue b/src/layouts/components/Notice.vue
new file mode 100644
index 0000000..33f140b
--- /dev/null
+++ b/src/layouts/components/Notice.vue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/Search.vue b/src/layouts/components/Search.vue
new file mode 100644
index 0000000..15f6b43
--- /dev/null
+++ b/src/layouts/components/Search.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/SideNav.vue b/src/layouts/components/SideNav.vue
new file mode 100644
index 0000000..7ec12d5
--- /dev/null
+++ b/src/layouts/components/SideNav.vue
@@ -0,0 +1,157 @@
+
+
+
+
+ handleNav('/dashboard/base')">
+
+
+
+
+
+
+
+ {{association.association_name}}
+
+
+
+
+
+
+
diff --git a/src/layouts/index.vue b/src/layouts/index.vue
new file mode 100644
index 0000000..8b6c643
--- /dev/null
+++ b/src/layouts/index.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/setting.vue b/src/layouts/setting.vue
new file mode 100644
index 0000000..ff71218
--- /dev/null
+++ b/src/layouts/setting.vue
@@ -0,0 +1,404 @@
+
+
+
+
+
+ 主题模式
+
+
+
+ 主题色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 导航布局
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 元素开关
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
请复制后手动修改配置文件: /src/config/style.ts
+
复制配置项
+
+
+
+
+
+
+
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 0000000..321d8af
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import { sync } from 'vuex-router-sync';
+import TDesign from 'tdesign-vue';
+import VueClipboard from 'vue-clipboard2';
+import axiosInstance from '@/utils/request';
+import App from './App.vue';
+import router from './router';
+import zhConfig from 'tdesign-vue/es/locale/zh_CN';
+// import enConfig from 'tdesign-vue/es/locale/en_US'; // 英文多语言配置
+
+import 'tdesign-vue/es/style/index.css';
+import '@/style/index.less';
+
+import './permission';
+import store from './store';
+
+Vue.use(VueRouter);
+Vue.use(TDesign);
+Vue.use(VueClipboard);
+
+Vue.component('t-page-header');
+
+Vue.prototype.$request = axiosInstance;
+
+const originPush = VueRouter.prototype.push;
+VueRouter.prototype.push = function push(location) {
+ return originPush.call(this, location).catch((err) => err);
+};
+
+const originReplace = VueRouter.prototype.replace;
+VueRouter.prototype.replace = function replace(location) {
+ return originReplace.call(this, location).catch((err) => err);
+};
+
+Vue.config.productionTip = false;
+sync(store, router);
+new Vue({
+ router,
+ store,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ render: (h) => (
+
+ {/* 可以通过config-provider提供全局(多语言、全局属性)配置,如
+
*/}
+
+
+
+
+ ),
+}).$mount('#app');
diff --git a/src/pages/activity/activity_index.vue b/src/pages/activity/activity_index.vue
new file mode 100644
index 0000000..d221e60
--- /dev/null
+++ b/src/pages/activity/activity_index.vue
@@ -0,0 +1,367 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onCreated(e)"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/association/index.vue b/src/pages/association/index.vue
new file mode 100644
index 0000000..f723fbc
--- /dev/null
+++ b/src/pages/association/index.vue
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/base/components/MiddleChart.vue b/src/pages/dashboard/base/components/MiddleChart.vue
new file mode 100644
index 0000000..b1f5a35
--- /dev/null
+++ b/src/pages/dashboard/base/components/MiddleChart.vue
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/base/components/OutputOverview.vue b/src/pages/dashboard/base/components/OutputOverview.vue
new file mode 100644
index 0000000..befb99c
--- /dev/null
+++ b/src/pages/dashboard/base/components/OutputOverview.vue
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 导出数据
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/base/components/RankList.vue b/src/pages/dashboard/base/components/RankList.vue
new file mode 100644
index 0000000..e8a4020
--- /dev/null
+++ b/src/pages/dashboard/base/components/RankList.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+ 本周
+ 近三个月
+
+
+
+
+
+ {{ rowIndex + 1 }}
+
+
+
+
+
+
+ 详情
+
+
+
+
+
+
+
+
+ 本周
+ 近三个月
+
+
+
+
+
+ {{ rowIndex + 1 }}
+
+
+
+
+
+
+ 详情
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/base/components/TopPanel.vue b/src/pages/dashboard/base/components/TopPanel.vue
new file mode 100644
index 0000000..53482af
--- /dev/null
+++ b/src/pages/dashboard/base/components/TopPanel.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+ {{ item.number }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/base/index.ts b/src/pages/dashboard/base/index.ts
new file mode 100644
index 0000000..63e8a2f
--- /dev/null
+++ b/src/pages/dashboard/base/index.ts
@@ -0,0 +1,702 @@
+import dayjs from 'dayjs';
+import { getChartListColor } from '@/utils/color';
+import { getRandomArray } from '@/utils/charts';
+
+/** 首页 dashboard 折线图 */
+export function constructInitDashboardDataset(type: string) {
+ const dateArray: Array = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
+ const datasetAxis = {
+ xAxis: {
+ type: 'category',
+ show: false,
+ data: dateArray,
+ },
+ yAxis: {
+ show: false,
+ type: 'value',
+ },
+ grid: {
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ },
+ };
+
+ if (type === 'line') {
+ const lineDataset = {
+ ...datasetAxis,
+ color: ['#fff'],
+ series: [
+ {
+ data: [150, 230, 224, 218, 135, 147, 260],
+ type,
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 0,
+ markPoint: {
+ data: [
+ { type: 'max', name: '最大值' },
+ { type: 'min', name: '最小值' },
+ ],
+ },
+ itemStyle: {
+ normal: {
+ lineStyle: {
+ width: 2,
+ },
+ },
+ },
+ },
+ ],
+ };
+ return lineDataset;
+ }
+ if (type === 'bar') {
+ const barDataset = {
+ ...datasetAxis,
+ color: getChartListColor(),
+ series: [
+ {
+ data: [
+ 100,
+ 130,
+ 184,
+ 218,
+ {
+ value: 135,
+ itemStyle: {
+ opacity: 0.2,
+ },
+ },
+ {
+ value: 118,
+ itemStyle: {
+ opacity: 0.2,
+ },
+ },
+ {
+ value: 60,
+ itemStyle: {
+ opacity: 0.2,
+ },
+ },
+ ],
+ type,
+ barWidth: 9,
+ },
+ ],
+ };
+ return barDataset;
+ }
+}
+
+/** 柱状图数据源 */
+export function constructInitDataset({
+ dateTime = [],
+ placeholderColor,
+ borderColor,
+}: { dateTime: Array } & Record) {
+ const divideNum = 10;
+ const timeArray = [];
+ const inArray = [];
+ const outArray = [];
+ for (let i = 0; i < divideNum; i++) {
+ if (dateTime.length > 0) {
+ const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
+ const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
+ timeArray.push(dayjs(enhandTime).format('MM-DD'));
+ } else {
+ timeArray.push(
+ dayjs()
+ .subtract(divideNum - i, 'day')
+ .format('MM-DD'),
+ );
+ }
+
+ inArray.push(getRandomArray().toString());
+ outArray.push(getRandomArray().toString());
+ }
+ const dataset = {
+ color: getChartListColor(),
+ tooltip: {
+ trigger: 'item',
+ },
+ xAxis: {
+ type: 'category',
+ data: timeArray,
+ axisLabel: {
+ color: placeholderColor,
+ },
+ axisLine: {
+ lineStyle: {
+ color: borderColor,
+ width: 1,
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: placeholderColor,
+ },
+ splitLine: {
+ lineStyle: {
+ color: borderColor,
+ },
+ },
+ },
+ grid: {
+ top: '5%',
+ left: '25px',
+ right: 0,
+ bottom: '60px',
+ },
+ legend: {
+ icon: 'rect',
+ itemWidth: 12,
+ itemHeight: 4,
+ itemGap: 48,
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal',
+ data: ['本月', '上月'],
+ },
+ series: [
+ {
+ name: '本月',
+ data: outArray,
+ type: 'bar',
+ },
+ {
+ name: '上月',
+ data: inArray,
+ type: 'bar',
+ },
+ ],
+ };
+
+ return dataset;
+}
+
+export function getLineChartDataSet({
+ dateTime = [],
+ placeholderColor,
+ borderColor,
+}: { dateTime?: Array } & Record) {
+ const divideNum = 10;
+ const timeArray = [];
+ const inArray = [];
+ const outArray = [];
+ for (let i = 0; i < divideNum; i++) {
+ if (dateTime.length > 0) {
+ const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
+ const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
+ timeArray.push(dayjs(enhandTime).format('MM-DD'));
+ } else {
+ timeArray.push(
+ dayjs()
+ .subtract(divideNum - i, 'day')
+ .format('MM-DD'),
+ );
+ }
+
+ inArray.push(getRandomArray().toString());
+ outArray.push(getRandomArray().toString());
+ }
+
+ const dataSet = {
+ color: getChartListColor(),
+ tooltip: {
+ trigger: 'item',
+ },
+ grid: {
+ left: '0',
+ right: '20px',
+ top: '5px',
+ bottom: '36px',
+ containLabel: true,
+ },
+ legend: {
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['本月', '上月'],
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ },
+ xAxis: {
+ type: 'category',
+ data: timeArray,
+ boundaryGap: false,
+ axisLabel: {
+ color: placeholderColor,
+ },
+ axisLine: {
+ lineStyle: {
+ width: 1,
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: placeholderColor,
+ },
+ splitLine: {
+ lineStyle: {
+ color: borderColor,
+ },
+ },
+ },
+ series: [
+ {
+ name: '本月',
+ data: outArray,
+ type: 'line',
+ smooth: false,
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ areaStyle: {
+ normal: {
+ opacity: 0.1,
+ },
+ },
+ },
+ {
+ name: '上月',
+ data: inArray,
+ type: 'line',
+ smooth: false,
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ },
+ ],
+ };
+ return dataSet;
+}
+
+/**
+ * 获取表行数据
+ *
+ * @export
+ * @param {string} productName
+ * @param {number} divideNum
+ */
+export function getSelftItemList(productName: string, divideNum: number): string[] {
+ const productArray: string[] = [productName];
+ for (let i = 0; i < divideNum; i++) {
+ productArray.push(getRandomArray(100 * i).toString());
+ }
+
+ return productArray;
+}
+
+/**
+ * 散点图数据
+ *
+ * @export
+ * @returns {any[]}
+ */
+export function getScatterDataSet({
+ dateTime = [],
+ placeholderColor,
+ borderColor,
+}: { dateTime?: Array } & Record): any {
+ const divideNum = 40;
+ const timeArray = [];
+ const inArray = [];
+ const outArray = [];
+ for (let i = 0; i < divideNum; i++) {
+ // const [timeArray, inArray, outArray] = dataset;
+ if (dateTime.length > 0) {
+ const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
+ const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
+ timeArray.push(dayjs(enhandTime).format('MM-DD'));
+ } else {
+ timeArray.push(
+ dayjs()
+ .subtract(divideNum - i, 'day')
+ .format('MM-DD'),
+ );
+ }
+
+ inArray.push(getRandomArray().toString());
+ outArray.push(getRandomArray().toString());
+ }
+
+ return {
+ color: getChartListColor(),
+ xAxis: {
+ data: timeArray,
+ axisLabel: {
+ color: placeholderColor,
+ },
+ splitLine: { show: false },
+ axisLine: {
+ lineStyle: {
+ color: borderColor,
+ width: 1,
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ // splitLine: { show: false},
+ axisLabel: {
+ color: placeholderColor,
+ },
+ nameTextStyle: {
+ padding: [0, 0, 0, 60],
+ },
+ axisTick: {
+ show: false,
+ axisLine: {
+ show: false,
+ },
+ },
+ axisLine: {
+ show: false,
+ },
+ splitLine: {
+ lineStyle: {
+ color: borderColor,
+ },
+ },
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ grid: {
+ top: '5px',
+ left: '25px',
+ right: '5px',
+ bottom: '60px',
+ },
+ legend: {
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['按摩仪', '咖啡机'],
+ itemHeight: 8,
+ itemWidth: 8,
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ },
+ series: [
+ {
+ name: '按摩仪',
+ symbolSize: 10,
+ data: outArray.reverse(),
+ type: 'scatter',
+ },
+ {
+ name: '咖啡机',
+ symbolSize: 10,
+ data: inArray.concat(inArray.reverse()),
+ type: 'scatter',
+ },
+ ],
+ };
+}
+
+/**
+ * 获域图数据结构
+ *
+ * @export
+ * @returns {any[]}
+ */
+export function getAreaChartDataSet(): any {
+ const xAxisData = [];
+ const data1 = [];
+ const data2 = [];
+ for (let i = 0; i < 50; i++) {
+ xAxisData.push(`${i}`);
+ data1.push((getRandomArray() * Math.sin(i / 5) * (i / 5 - 5) + i / 6) * 2);
+ data2.push((getRandomArray() * Math.cos(i / 5) * (i / 5 - 5) + i / 6) * 2);
+ }
+
+ return {
+ color: getChartListColor(),
+ // title: {
+ // text: '柱状图动画延迟',
+ // },
+ legend: {
+ left: 'center',
+ bottom: '5%',
+ orient: 'horizontal',
+ data: ['测试', '上线'],
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ xAxis: {
+ data: xAxisData,
+ splitLine: {
+ show: false,
+ },
+ },
+ yAxis: {},
+ series: [
+ {
+ name: '测试',
+ type: 'bar',
+ data: data1,
+ emphasis: {
+ focus: 'series',
+ },
+ animationDelay(idx: number) {
+ return idx * 10;
+ },
+ },
+ {
+ name: '上线',
+ type: 'bar',
+ data: data2,
+ emphasis: {
+ focus: 'series',
+ },
+ animationDelay(idx: number) {
+ return idx * 10 + 100;
+ },
+ },
+ ],
+ animationEasing: 'elasticOut',
+ animationDelayUpdate(idx: number) {
+ return idx * 5;
+ },
+ };
+}
+
+/**
+ * 柱状图数据结构
+ *
+ * @export
+ * @param {boolean} [isMonth=false]
+ * @returns {*}
+ */
+export function getColumnChartDataSet(isMonth = false) {
+ if (isMonth) {
+ return {
+ color: getChartListColor(),
+ legend: {
+ left: 'center',
+ top: '10%',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['直接访问'],
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ // 坐标轴指示器,坐标轴触发有效
+ type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
+ },
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true,
+ },
+ xAxis: [
+ {
+ type: 'category',
+ data: ['1', '4', '8', '12', '16', '20', '24'],
+ axisTick: {
+ alignWithLabel: true,
+ },
+ },
+ ],
+ yAxis: [
+ {
+ type: 'value',
+ },
+ ],
+ series: [
+ {
+ name: '直接访问',
+ type: 'bar',
+ barWidth: '60%',
+ data: [
+ getRandomArray(Math.random() * 100),
+ getRandomArray(Math.random() * 200),
+ getRandomArray(Math.random() * 300),
+ getRandomArray(Math.random() * 400),
+ getRandomArray(Math.random() * 500),
+ getRandomArray(Math.random() * 600),
+ getRandomArray(Math.random() * 700),
+ ],
+ },
+ ],
+ };
+ }
+
+ return {
+ color: getChartListColor(),
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ // 坐标轴指示器,坐标轴触发有效
+ type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
+ },
+ },
+ legend: {
+ left: 'center',
+ bottom: '0%',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['直接访问'],
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '13%',
+ containLabel: true,
+ },
+ xAxis: [
+ {
+ type: 'category',
+ data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
+ axisTick: {
+ alignWithLabel: true,
+ },
+ },
+ ],
+ yAxis: [
+ {
+ type: 'value',
+ },
+ ],
+ series: [
+ {
+ name: '直接访问',
+ type: 'bar',
+ barWidth: '20%',
+ data: [
+ getRandomArray(Math.random() * 100),
+ getRandomArray(Math.random() * 200),
+ getRandomArray(Math.random() * 300),
+ getRandomArray(Math.random() * 400),
+ getRandomArray(Math.random() * 500),
+ getRandomArray(Math.random() * 600),
+ getRandomArray(Math.random() * 700),
+ ],
+ },
+ ],
+ };
+}
+
+export function getPieChartDataSet({
+ radius = 42,
+ textColor,
+ placeholderColor,
+ containerColor,
+}: { radius: number } & Record) {
+ return {
+ color: getChartListColor(),
+ tooltip: {
+ show: false,
+ trigger: 'axis',
+ position: null,
+ },
+ grid: {
+ top: '0',
+ right: '0',
+ },
+ legend: {
+ selectedMode: false,
+ itemWidth: 12,
+ itemHeight: 4,
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal', // legend 横向布局。
+ },
+ series: [
+ {
+ name: '销售渠道',
+ type: 'pie',
+ radius: ['48%', '60%'],
+ avoidLabelOverlap: true,
+ selectedMode: true,
+ hoverAnimation: true,
+ silent: true,
+ itemStyle: {
+ borderColor: containerColor,
+ borderWidth: 1,
+ },
+ label: {
+ show: true,
+ position: 'center',
+ formatter: ['{value|{d}%}', '{name|{b}渠道占比}'].join('\n'),
+ rich: {
+ value: {
+ color: textColor,
+ fontSize: 28,
+ fontWeight: 'normal',
+ lineHeight: 46,
+ },
+ name: {
+ color: '#909399',
+ fontSize: 12,
+ lineHeight: 14,
+ },
+ },
+ },
+ emphasis: {
+ label: {
+ show: true,
+ formatter: ['{value|{d}%}', '{name|{b}渠道占比}'].join('\n'),
+ rich: {
+ value: {
+ color: textColor,
+ fontSize: 28,
+ fontWeight: 'normal',
+ lineHeight: 46,
+ },
+ name: {
+ color: '#909399',
+ fontSize: 14,
+ lineHeight: 14,
+ },
+ },
+ },
+ },
+ labelLine: {
+ show: false,
+ },
+ data: [
+ {
+ value: 1048,
+ name: '线上',
+ },
+ { value: radius * 7, name: '门店' },
+ ],
+ },
+ ],
+ };
+}
diff --git a/src/pages/dashboard/base/index.vue b/src/pages/dashboard/base/index.vue
new file mode 100644
index 0000000..f68e79d
--- /dev/null
+++ b/src/pages/dashboard/base/index.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/dashboard/detail/index.ts b/src/pages/dashboard/detail/index.ts
new file mode 100644
index 0000000..c8efbe1
--- /dev/null
+++ b/src/pages/dashboard/detail/index.ts
@@ -0,0 +1,267 @@
+import dayjs from 'dayjs';
+import { getChartListColor } from '@/utils/color';
+import { getDateArray, getRandomArray } from '@/utils/charts';
+
+/**
+ * 散点图数据
+ *
+ * @export
+ * @returns {any[]}
+ */
+export function getScatterDataSet({
+ dateTime = [],
+ placeholderColor,
+ borderColor,
+}: { dateTime?: Array } & Record): any {
+ const divideNum = 40;
+ const timeArray = [];
+ const inArray = [];
+ const outArray = [];
+ for (let i = 0; i < divideNum; i++) {
+ // const [timeArray, inArray, outArray] = dataset;
+ if (dateTime.length > 0) {
+ const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
+ const endTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
+ timeArray.push(dayjs(endTime).format('MM-DD'));
+ } else {
+ timeArray.push(
+ dayjs()
+ .subtract(divideNum - i, 'day')
+ .format('MM-DD'),
+ );
+ }
+
+ inArray.push(getRandomArray().toString());
+ outArray.push(getRandomArray().toString());
+ }
+
+ return {
+ color: getChartListColor(),
+ xAxis: {
+ data: timeArray,
+ axisLabel: {
+ color: placeholderColor,
+ },
+ splitLine: { show: false },
+ axisLine: {
+ lineStyle: {
+ color: borderColor,
+ width: 1,
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ // splitLine: { show: false},
+ axisLabel: {
+ color: placeholderColor,
+ },
+ nameTextStyle: {
+ padding: [0, 0, 0, 60],
+ },
+ axisTick: {
+ show: false,
+ axisLine: {
+ show: false,
+ },
+ },
+ axisLine: {
+ show: false,
+ },
+ splitLine: {
+ lineStyle: {
+ color: borderColor,
+ },
+ },
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ grid: {
+ top: '5px',
+ left: '25px',
+ right: '5px',
+ bottom: '60px',
+ },
+ legend: {
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['按摩仪', '咖啡机'],
+ itemHeight: 8,
+ itemWidth: 8,
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ },
+ series: [
+ {
+ name: '按摩仪',
+ symbolSize: 10,
+ data: outArray.reverse(),
+ type: 'scatter',
+ },
+ {
+ name: '咖啡机',
+ symbolSize: 10,
+ data: inArray.concat(inArray.reverse()),
+ type: 'scatter',
+ },
+ ],
+ };
+}
+
+/** 折线图数据 */
+export function getFolderLineDataSet({
+ dateTime = [],
+ placeholderColor,
+ borderColor,
+}: { dateTime?: Array } & Record) {
+ let dateArray: Array = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
+ if (dateTime.length > 0) {
+ const divideNum = 7;
+ dateArray = getDateArray(dateTime, divideNum);
+ }
+ return {
+ color: getChartListColor(),
+ grid: {
+ top: '5%',
+ right: '10px',
+ left: '30px',
+ bottom: '60px',
+ },
+ legend: {
+ left: 'center',
+ bottom: '0',
+ orient: 'horizontal', // legend 横向布局。
+ data: ['杯子', '茶叶', '蜂蜜', '面粉'],
+ textStyle: {
+ fontSize: 12,
+ color: placeholderColor,
+ },
+ },
+ xAxis: {
+ type: 'category',
+ data: dateArray,
+ boundaryGap: false,
+ axisLabel: {
+ color: placeholderColor,
+ },
+ axisLine: {
+ lineStyle: {
+ color: borderColor,
+ width: 1,
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: placeholderColor,
+ },
+ splitLine: {
+ lineStyle: {
+ color: borderColor,
+ },
+ },
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ series: [
+ {
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ name: '杯子',
+ stack: '总量',
+ data: [
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ ],
+ type: 'line',
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ },
+ {
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ name: '茶叶',
+ stack: '总量',
+ data: [
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ ],
+ type: 'line',
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ },
+ {
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ name: '蜂蜜',
+ stack: '总量',
+ data: [
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ ],
+ type: 'line',
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ },
+ {
+ showSymbol: true,
+ symbol: 'circle',
+ symbolSize: 8,
+ name: '面粉',
+ stack: '总量',
+ data: [
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ getRandomArray(),
+ ],
+ type: 'line',
+ itemStyle: {
+ normal: {
+ borderColor,
+ borderWidth: 1,
+ },
+ },
+ },
+ ],
+ };
+}
diff --git a/src/pages/dashboard/detail/index.vue b/src/pages/dashboard/detail/index.vue
new file mode 100644
index 0000000..8719a1b
--- /dev/null
+++ b/src/pages/dashboard/detail/index.vue
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+ {{ item.number }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 导出数据
+
+
+
+
+
+
+
diff --git a/src/pages/login/index.less b/src/pages/login/index.less
new file mode 100644
index 0000000..13d38ec
--- /dev/null
+++ b/src/pages/login/index.less
@@ -0,0 +1,202 @@
+@import '@/style/variables.less';
+
+.light {
+ &.login-wrapper {
+ background-color: white;
+ background-image: url('@/assets/assets-login-bg-white.png');
+ }
+}
+
+.dark {
+ &.login-wrapper {
+ background-color: var(--td-bg-color-page);
+ background-image: url('@/assets/assets-login-bg-black.png');
+ }
+}
+
+.login-wrapper {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background-size: cover;
+ background-position: 100%;
+ position: relative;
+}
+
+.login-container {
+ position: absolute;
+ top: 22%;
+ left: 5%;
+ min-height: 500px;
+ line-height: 22px;
+}
+
+.title-container {
+ .title {
+ font-size: 36px;
+ line-height: 44px;
+ color: var(--td-text-color-primary);
+ margin-top: 4px;
+
+ &.margin-no {
+ margin-top: 0;
+ }
+ }
+
+ .sub-title {
+ margin-top: 16px;
+
+ .tip {
+ display: inline-block;
+ margin-right: 8px;
+ font-size: 14px;
+
+ &:first-child {
+ color: var(--td-text-color-secondary);
+ }
+
+ &:last-child {
+ color: var(--td-text-color-primary);
+ cursor: pointer;
+ }
+ }
+ }
+}
+
+.item-container {
+ width: 400px;
+ margin-top: 48px;
+
+ &.login-qrcode {
+ .tip-container {
+ width: 192px;
+ margin-bottom: 16px;
+ font-size: 14px;
+ display: flex;
+ justify-content: space-between;
+
+ .tip {
+ color: var(--td-text-color-primary);
+ }
+
+ .refresh {
+ display: flex;
+ align-items: center;
+ color: var(--td-brand-color);
+
+ .t-icon {
+ font-size: 14px;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .bottom-container {
+ margin-top: 32px;
+ }
+ }
+
+ &.login-phone {
+ .bottom-container {
+ margin-top: 66px;
+ }
+ }
+
+ .check-container {
+ display: flex;
+ align-items: center;
+
+ &.remember-pwd {
+ margin-bottom: 16px;
+ justify-content: space-between;
+ }
+
+ .t-checkbox__label {
+ color: var(--td-text-color-secondary);
+ }
+
+ span {
+ color: var(--td-brand-color);
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .verification-code {
+ display: flex;
+ align-items: center;
+
+ .t-form__controls {
+ width: 100%;
+
+ button {
+ flex-shrink: 0;
+ width: 102px;
+ height: 40px;
+ margin-left: 11px;
+ }
+ }
+ }
+
+ .btn-container {
+ margin-top: 48px;
+ }
+}
+
+.switch-container {
+ margin-top: 24px;
+
+ .tip {
+ font-size: 14px;
+ color: var(--td-brand-color);
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ margin-right: 14px;
+
+ &:last-child {
+ &::after {
+ display: none;
+ }
+ }
+
+ &::after {
+ content: '';
+ display: block;
+ width: 1px;
+ height: 12px;
+ background: var(--td-gray-color-3);
+ margin-left: 14px;
+ }
+ }
+}
+
+.check-container {
+ font-size: 14px;
+ color: var(--td-text-color-secondary);
+
+ .tip {
+ float: right;
+ font-size: 14px;
+ color: var(--td-brand-color);
+ }
+}
+
+.copyright {
+ font-size: 14px;
+ position: absolute;
+ left: 5%;
+ bottom: var(--td-comp-size-xxxl);
+ color: var(--td-text-color-secondary);
+}
+
+@media screen and (max-height: 700px) {
+ .copyright {
+ display: none;
+ }
+}
diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue
new file mode 100644
index 0000000..733310b
--- /dev/null
+++ b/src/pages/login/index.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
登录到
+ {{info.association_name}}
+ 智慧云商协后台管理系统
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
记住账号
+
+ 会员注册
+ 会员登录
+
+
+
+
+ 登录
+
+
+
+
+
Copyright @ 2021-2022 Tencent. All Rights Reserved
+
+
+
+
diff --git a/src/pages/news/news_index.vue b/src/pages/news/news_index.vue
new file mode 100644
index 0000000..dd764a6
--- /dev/null
+++ b/src/pages/news/news_index.vue
@@ -0,0 +1,327 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ onCreated(e)"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/register/index.less b/src/pages/register/index.less
new file mode 100644
index 0000000..13d38ec
--- /dev/null
+++ b/src/pages/register/index.less
@@ -0,0 +1,202 @@
+@import '@/style/variables.less';
+
+.light {
+ &.login-wrapper {
+ background-color: white;
+ background-image: url('@/assets/assets-login-bg-white.png');
+ }
+}
+
+.dark {
+ &.login-wrapper {
+ background-color: var(--td-bg-color-page);
+ background-image: url('@/assets/assets-login-bg-black.png');
+ }
+}
+
+.login-wrapper {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background-size: cover;
+ background-position: 100%;
+ position: relative;
+}
+
+.login-container {
+ position: absolute;
+ top: 22%;
+ left: 5%;
+ min-height: 500px;
+ line-height: 22px;
+}
+
+.title-container {
+ .title {
+ font-size: 36px;
+ line-height: 44px;
+ color: var(--td-text-color-primary);
+ margin-top: 4px;
+
+ &.margin-no {
+ margin-top: 0;
+ }
+ }
+
+ .sub-title {
+ margin-top: 16px;
+
+ .tip {
+ display: inline-block;
+ margin-right: 8px;
+ font-size: 14px;
+
+ &:first-child {
+ color: var(--td-text-color-secondary);
+ }
+
+ &:last-child {
+ color: var(--td-text-color-primary);
+ cursor: pointer;
+ }
+ }
+ }
+}
+
+.item-container {
+ width: 400px;
+ margin-top: 48px;
+
+ &.login-qrcode {
+ .tip-container {
+ width: 192px;
+ margin-bottom: 16px;
+ font-size: 14px;
+ display: flex;
+ justify-content: space-between;
+
+ .tip {
+ color: var(--td-text-color-primary);
+ }
+
+ .refresh {
+ display: flex;
+ align-items: center;
+ color: var(--td-brand-color);
+
+ .t-icon {
+ font-size: 14px;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .bottom-container {
+ margin-top: 32px;
+ }
+ }
+
+ &.login-phone {
+ .bottom-container {
+ margin-top: 66px;
+ }
+ }
+
+ .check-container {
+ display: flex;
+ align-items: center;
+
+ &.remember-pwd {
+ margin-bottom: 16px;
+ justify-content: space-between;
+ }
+
+ .t-checkbox__label {
+ color: var(--td-text-color-secondary);
+ }
+
+ span {
+ color: var(--td-brand-color);
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .verification-code {
+ display: flex;
+ align-items: center;
+
+ .t-form__controls {
+ width: 100%;
+
+ button {
+ flex-shrink: 0;
+ width: 102px;
+ height: 40px;
+ margin-left: 11px;
+ }
+ }
+ }
+
+ .btn-container {
+ margin-top: 48px;
+ }
+}
+
+.switch-container {
+ margin-top: 24px;
+
+ .tip {
+ font-size: 14px;
+ color: var(--td-brand-color);
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ margin-right: 14px;
+
+ &:last-child {
+ &::after {
+ display: none;
+ }
+ }
+
+ &::after {
+ content: '';
+ display: block;
+ width: 1px;
+ height: 12px;
+ background: var(--td-gray-color-3);
+ margin-left: 14px;
+ }
+ }
+}
+
+.check-container {
+ font-size: 14px;
+ color: var(--td-text-color-secondary);
+
+ .tip {
+ float: right;
+ font-size: 14px;
+ color: var(--td-brand-color);
+ }
+}
+
+.copyright {
+ font-size: 14px;
+ position: absolute;
+ left: 5%;
+ bottom: var(--td-comp-size-xxxl);
+ color: var(--td-text-color-secondary);
+}
+
+@media screen and (max-height: 700px) {
+ .copyright {
+ display: none;
+ }
+}
diff --git a/src/pages/register/index.vue b/src/pages/register/index.vue
new file mode 100644
index 0000000..bfe5c20
--- /dev/null
+++ b/src/pages/register/index.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 同意安装协议
+
+
+ 下一步
+
+
+
+
+
+
+
+
+ {{ row.value }}
+ {{ row.value }}
+
+
+
+
+
+ 重新检测
+ 下一步
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/user/user_index.vue b/src/pages/user/user_index.vue
new file mode 100644
index 0000000..3374665
--- /dev/null
+++ b/src/pages/user/user_index.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
diff --git a/src/pages/user/user_info.vue b/src/pages/user/user_info.vue
new file mode 100644
index 0000000..0fc9cfa
--- /dev/null
+++ b/src/pages/user/user_info.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{info.gender==1?"男":"女"}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{info.if_list==1?"否":"是"}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{info.if_organization==1?"否":"是"}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/user/user_line.vue b/src/pages/user/user_line.vue
new file mode 100644
index 0000000..650e45f
--- /dev/null
+++ b/src/pages/user/user_line.vue
@@ -0,0 +1,136 @@
+
+
+
+ 新增
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/user/user_plan.vue b/src/pages/user/user_plan.vue
new file mode 100644
index 0000000..fa7c749
--- /dev/null
+++ b/src/pages/user/user_plan.vue
@@ -0,0 +1,128 @@
+
+
+
+ 新增
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/permission.js b/src/permission.js
new file mode 100644
index 0000000..a8ec9a6
--- /dev/null
+++ b/src/permission.js
@@ -0,0 +1,53 @@
+import NProgress from 'nprogress'; // progress bar
+import 'nprogress/nprogress.css'; // progress bar style
+
+import store from '@/store';
+import router from '@/router';
+
+NProgress.configure({ showSpinner: false });
+
+const whiteListRouters = store.getters['permission/whiteListRouters'];
+
+router.beforeEach(async (to, from, next) => {
+ NProgress.start();
+ document.title = '智慧云商协-'+to.meta.title;
+ const token = localStorage.getItem('associationToken');
+ console.log(token);
+ console.log(to.path);
+ if (token) {
+ if (to.path === '/login') {
+ next();
+ return;
+ }
+
+ const roles = store.getters['user/roles'];
+ console.log(roles);
+ if (roles && roles.length > 0) {
+ next();
+ } else {
+ try {
+ await store.dispatch('user/getUserInfo');
+
+ await store.dispatch('permission/initRoutes', store.getters['user/roles']);
+
+ next({ ...to });
+ } catch (error) {
+ await store.commit('user/removeToken');
+ next(`/login?redirect=${to.path}`);
+ NProgress.done();
+ }
+ }
+ } else {
+ /* white list router */
+ if (whiteListRouters.indexOf(to.path) !== -1) {
+ next();
+ } else {
+ next(`/login`);
+ }
+ NProgress.done();
+ }
+});
+
+router.afterEach(() => {
+ NProgress.done();
+});
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..b52e50d
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,50 @@
+import VueRouter from 'vue-router';
+
+import baseRouters from './modules/base';
+import componentsRouters from './modules/components';
+const env = import.meta.env.MODE || 'development';
+
+// 存放动态路由
+export const asyncRouterList = [...baseRouters, ...componentsRouters];
+
+// 存放固定的路由
+const defaultRouterList = [
+ {
+ path: '/login',
+ name: 'login',
+ meta: {
+ title: '登录',
+ },
+ component: () => import('@/pages/login/index.vue'),
+ },
+ {
+ path: '/register',
+ name: 'register',
+ meta: {title: '会员注册'},
+ component: () => import('@/pages/register/index.vue'),
+ },
+ {
+ path: '*',
+ redirect: '/dashboard/base',
+ },
+ ...asyncRouterList,
+];
+
+const createRouter = () =>
+ new VueRouter({
+ mode: 'hash',
+ base: env === 'site' ? '/starter/vue/' : null,
+ routes: defaultRouterList,
+ scrollBehavior() {
+ return { x: 0, y: 0 };
+ },
+ });
+
+const router = createRouter();
+
+export function resetRouter() {
+ const newRouter = createRouter();
+ router.matcher = newRouter.matcher; // reset router
+}
+
+export default router;
diff --git a/src/router/modules/base.ts b/src/router/modules/base.ts
new file mode 100644
index 0000000..2ea9684
--- /dev/null
+++ b/src/router/modules/base.ts
@@ -0,0 +1,23 @@
+import { DashboardIcon } from 'tdesign-icons-vue';
+import Layout from '@/layouts/index.vue';
+
+export default [
+ {
+ path: '/dashboard',
+ component: Layout,
+ redirect: '/dashboard/base',
+ name: 'dashboard',
+ meta: {
+ title: '首页',
+ icon: DashboardIcon,
+ },
+ children: [
+ {
+ path: 'base',
+ name: 'DashboardBase',
+ component: () => import('@/pages/dashboard/base/index.vue'),
+ meta: { title: '数据大屏' },
+ }
+ ],
+ },
+];
diff --git a/src/router/modules/components.ts b/src/router/modules/components.ts
new file mode 100644
index 0000000..e3bcfb7
--- /dev/null
+++ b/src/router/modules/components.ts
@@ -0,0 +1,84 @@
+import { ViewModuleIcon, UsergroupIcon,ViewListIcon,ChartBubbleIcon,HomeIcon,HelpIcon} from 'tdesign-icons-vue';
+
+import Layout from '@/layouts/index.vue';
+
+export default [
+ {
+ path: '/user',
+ name: 'user',
+ component: Layout,
+ redirect: '/user/user_index',
+ meta: { title: '会员管理', icon: UsergroupIcon },
+ children: [
+ {
+ path: 'user_index',
+ name: 'userIndex',
+ component: () => import('@/pages/user/user_index.vue'),
+ meta: { title: '会员列表' },
+ },
+ {
+ path: 'user_plan',
+ name: 'userPlan',
+ component: () => import('@/pages/user/user_plan.vue'),
+ meta: { title: '职位管理' },
+ },
+ {
+ path: 'user_line',
+ name: 'userLine',
+ component: () => import('@/pages/user/user_line.vue'),
+ meta: { title: '行业管理' },
+ },
+ {
+ path: 'user_info',
+ name: 'userInfo',
+ component: () => import('@/pages/user/user_info.vue'),
+ meta: { title: '会员详情',hidden:true },
+ },
+ ],
+ },
+ {
+ path: '/activity',
+ name: 'activity',
+ component: Layout,
+ redirect: '/activity/index',
+ meta: { title: '活动管理', icon: ChartBubbleIcon },
+ children: [
+ {
+ path: 'activity_index',
+ name: 'activityIndex',
+ component: () => import('@/pages/activity/activity_index.vue'),
+ meta: { title: '活动列表' },
+ }
+ ],
+ },
+ {
+ path: '/news',
+ name: 'news',
+ component: Layout,
+ redirect: '/news/news_index',
+ meta: { title: '新闻管理', icon: ViewListIcon },
+ children: [
+ {
+ path: 'news_index',
+ name: 'newsIndex',
+ component: () => import('@/pages/news/news_index.vue'),
+ meta: { title: '新闻列表' },
+ }
+ ],
+ },{
+ path: '/association',
+ name: 'association',
+ component: Layout,
+ redirect: '/association/index',
+ meta: { title: '协会管理', icon: HomeIcon },
+ children: [
+ {
+ path: 'index',
+ name: 'associationIndex',
+ component: () => import('@/pages/association/index.vue'),
+ meta: { title: '关于我们' },
+ }
+ ],
+ },
+
+];
diff --git a/src/service/service-advance.ts b/src/service/service-advance.ts
new file mode 100644
index 0000000..de45eda
--- /dev/null
+++ b/src/service/service-advance.ts
@@ -0,0 +1,233 @@
+type AdvancedColumn = {
+ name: string;
+ value: string;
+ type?: any;
+};
+type TableItem = {
+ width?: string | number;
+ ellipsis?: any;
+ colKey: string;
+ title: string;
+ sorter?: any;
+ align?: string;
+ fixed?: string;
+ className?: string;
+};
+class DetailBase {
+ /**
+ * 下拉框选项数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getBaseInfoData(): Array {
+ return [
+ {
+ name: '合同名称',
+ value: '总部办公用品采购项目',
+ },
+ {
+ name: '合同状态',
+ value: '履行中',
+ type: {
+ key: 'contractStatus',
+ value: 'inProgress',
+ },
+ },
+ {
+ name: '合同编号',
+ value: 'BH00010',
+ },
+ {
+ name: '合同类型',
+ value: '主合同',
+ },
+ {
+ name: '合同收付类型',
+ value: '付款',
+ },
+ {
+ name: '合同金额',
+ value: '5,000,000元',
+ },
+ {
+ name: '甲方',
+ value: '腾讯科技(深圳)有限公司',
+ },
+ {
+ name: '乙方',
+ value: '欧尚',
+ },
+ {
+ name: '合同签订日期',
+ value: '2020-12-20',
+ },
+ {
+ name: '合同生效日期',
+ value: '2021-01-20',
+ },
+ {
+ name: '合同结束日期',
+ value: '2022-12-20',
+ },
+ {
+ name: '合同附件',
+ value: '总部办公用品采购项目合同.pdf',
+ type: {
+ key: 'contractAnnex',
+ value: 'pdf',
+ },
+ },
+ {
+ name: '备注',
+ value: '--',
+ },
+ {
+ name: '创建时间',
+ value: '2020-12-22 10:00:00',
+ },
+ ];
+ }
+
+ /**
+ * 表格定义基础数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getTableColumns(): Array {
+ return [
+ {
+ width: 300,
+ ellipsis: true,
+ colKey: 'index',
+ title: '申请号',
+ sorter: (a, b) => a.index.substr(3) - b.index.substr(3),
+ },
+ {
+ width: 200,
+ ellipsis: true,
+ colKey: 'pdName',
+ title: '产品名称',
+ sorter: (a, b) => a.pdName.length - b.pdName.length,
+ },
+ {
+ width: 200,
+ ellipsis: true,
+ colKey: 'pdNum',
+ title: '产品编号',
+ },
+ {
+ width: 200,
+ ellipsis: true,
+ colKey: 'purchaseNum',
+ title: '采购数量',
+ sorter: (a, b) => a.purchaseNum - b.purchaseNum,
+ },
+ {
+ width: 200,
+ ellipsis: true,
+ colKey: 'adminName',
+ title: '申请部门',
+ },
+ {
+ width: 200,
+ ellipsis: true,
+ colKey: 'updateTime',
+ title: '创建时间',
+ sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
+ },
+ {
+ align: 'left',
+ fixed: 'right',
+ width: 200,
+ className: 'test2',
+ colKey: 'op',
+ title: '操作',
+ },
+ ];
+ }
+
+ /**
+ * 获取弹窗配置数据
+ *
+ * @memberOf DetailBase
+ */
+ getPropUpData(): any {
+ const INITIAL_DATA = {
+ name: '',
+ warning: '',
+ success: '',
+ failB: '',
+ warningB: '',
+ loading: '',
+ add: '',
+ help: '',
+ };
+
+ return {
+ formData: { ...INITIAL_DATA },
+ courseOptions: [
+ { label: '语文', value: '1' },
+ { label: '数学', value: '2' },
+ { label: '英语', value: '3' },
+ ],
+ options: [
+ {
+ label: '资源初始化后',
+ value: 'beijing',
+ },
+ {
+ label: '上海',
+ value: 'shanghai',
+ },
+ ],
+ options1: [
+ {
+ label: '资源初始化后',
+ value: 'guangzhou',
+ },
+ {
+ label: '深圳',
+ value: 'shenzhen',
+ },
+ {
+ label: '东莞',
+ value: 'dongguang',
+ },
+ ],
+ options2: [
+ {
+ label: '资源初始化后',
+ value: 'nanjing',
+ },
+ {
+ label: '苏州',
+ value: '苏州',
+ },
+ {
+ label: '无锡',
+ value: 'wuxi',
+ },
+ ],
+ tSelectOptions: [
+ {
+ label: 'Sanzhang',
+ value: '1',
+ },
+ {
+ label: 'ls',
+ value: '2',
+ },
+ {
+ label: 'James',
+ value: '3',
+ },
+ ],
+ };
+ }
+}
+
+export default new DetailBase();
diff --git a/src/service/service-base.ts b/src/service/service-base.ts
new file mode 100644
index 0000000..37db069
--- /dev/null
+++ b/src/service/service-base.ts
@@ -0,0 +1,205 @@
+import { TdBaseTableProps } from 'tdesign-vue';
+
+interface DashboardPanel {
+ title: string;
+ number: string | number;
+ leftType: string;
+ upTrend?: string;
+ downTrend?: string;
+}
+
+interface TendItem {
+ growUp?: number;
+ productName: string;
+ count: number;
+ date: string;
+}
+
+export const PANE_LIST: Array = [
+ {
+ title: '总收入',
+ number: '¥ 28,425.00',
+ upTrend: '20.5%',
+ leftType: 'echarts-line',
+ },
+ {
+ title: '总退款',
+ number: '¥ 768.00',
+ downTrend: '20.5%',
+ leftType: 'echarts-bar',
+ },
+ {
+ title: '活跃用户(个)',
+ number: '1126',
+ downTrend: '20.5%',
+ leftType: 'icon-usergroup',
+ },
+ {
+ title: '订单(个)',
+ number: 527,
+ downTrend: '20.5%',
+ leftType: 'icon-file-paste',
+ },
+];
+
+export const SALE_TEND_LIST: Array = [
+ {
+ growUp: 1,
+ productName: '国家电网有限公司',
+ count: 7059,
+ date: '2021-09-01',
+ },
+ {
+ growUp: -1,
+ productName: '深圳燃气集团股份有限公司',
+ count: 6437,
+ date: '2021-09-01',
+ },
+ {
+ growUp: 4,
+ productName: '国家烟草专卖局',
+ count: 4221,
+ date: '2021-09-01',
+ },
+ {
+ growUp: 3,
+ productName: '中国电信集团有限公司',
+ count: 3317,
+ date: '2021-09-01',
+ },
+ {
+ growUp: -3,
+ productName: '中国移动通信集团有限公司',
+ count: 3015,
+ date: '2021-09-01',
+ },
+ {
+ growUp: -3,
+ productName: '新余市办公用户采购项目',
+ count: 2015,
+ date: '2021-09-12',
+ },
+];
+
+export const BUY_TEND_LIST: Array = [
+ {
+ growUp: 1,
+ productName: '腾讯科技(深圳)有限公司',
+ count: 3015,
+ date: '2021-09-01',
+ },
+ {
+ growUp: -1,
+ productName: '大润发有限公司',
+ count: 2015,
+ date: '2021-09-01',
+ },
+ {
+ growUp: 6,
+ productName: '四川海底捞股份有限公司',
+ count: 1815,
+ date: '2021-09-11',
+ },
+ {
+ growUp: -3,
+ productName: '索尼(中国)有限公司',
+ count: 1015,
+ date: '2021-09-21',
+ },
+ {
+ growUp: -4,
+ productName: '松下电器(中国)有限公司',
+ count: 445,
+ date: '2021-09-19',
+ },
+ {
+ growUp: -3,
+ productName: '新余市办公用户采购项目',
+ count: 2015,
+ date: '2021-09-12',
+ },
+];
+
+export const SALE_COLUMNS: TdBaseTableProps['columns'] = [
+ {
+ align: 'center',
+ colKey: 'index',
+ title: '排名',
+ width: 80,
+ fixed: 'left',
+ },
+ {
+ align: 'left',
+ ellipsis: true,
+ colKey: 'productName',
+ title: '客户名称',
+ minWidth: 200,
+ },
+ {
+ align: 'center',
+ colKey: 'growUp',
+ width: 100,
+ title: '较上周',
+ },
+ {
+ align: 'center',
+ colKey: 'count',
+ title: '订单量',
+ width: 100,
+ },
+ {
+ align: 'center',
+ colKey: 'date',
+ width: 140,
+ title: '合同签订日期',
+ },
+ {
+ align: 'center',
+ colKey: 'operation',
+ title: '操作',
+ width: 80,
+ fixed: 'right',
+ },
+];
+
+export const BUY_COLUMNS: TdBaseTableProps['columns'] = [
+ {
+ align: 'center',
+ colKey: 'index',
+ title: '排名',
+ width: 80,
+ fixed: 'left',
+ },
+ {
+ align: 'left',
+ ellipsis: true,
+ colKey: 'productName',
+ title: '供应商名称',
+ minWidth: 200,
+ },
+ {
+ align: 'center',
+ colKey: 'growUp',
+ width: 100,
+ title: '较上周',
+ },
+ {
+ align: 'center',
+ colKey: 'count',
+ title: '订单量',
+ width: 100,
+ },
+ {
+ align: 'center',
+ colKey: 'date',
+ width: 140,
+ title: '合同签订日期',
+ },
+ {
+ align: 'center',
+ colKey: 'operation',
+ title: '操作',
+ width: 80,
+ fixed: 'right',
+ },
+];
diff --git a/src/service/service-detail-base.ts b/src/service/service-detail-base.ts
new file mode 100644
index 0000000..df1edec
--- /dev/null
+++ b/src/service/service-detail-base.ts
@@ -0,0 +1,84 @@
+interface IAdvancedColumn {
+ name: string;
+ value: string;
+ type?: any;
+}
+class DetailBase {
+ /**
+ * 下拉框选项数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getBaseInfoData(): Array {
+ return [
+ {
+ name: '合同名称',
+ value: '总部办公用品采购项目',
+ },
+ {
+ name: '合同状态',
+ value: '履行中',
+ type: {
+ key: 'contractStatus',
+ value: 'inProgress',
+ },
+ },
+ {
+ name: '合同编号',
+ value: 'BH00010',
+ },
+ {
+ name: '合同类型',
+ value: '主合同',
+ },
+ {
+ name: '合同收付类型',
+ value: '付款',
+ },
+ {
+ name: '合同金额',
+ value: '5,000,000元',
+ },
+ {
+ name: '甲方',
+ value: '腾讯科技(深圳)有限公司',
+ },
+ {
+ name: '乙方',
+ value: '欧尚',
+ },
+ {
+ name: '合同签订日期',
+ value: '2020-12-20',
+ },
+ {
+ name: '合同生效日期',
+ value: '2021-01-20',
+ },
+ {
+ name: '合同结束日期',
+ value: '2022-12-20',
+ },
+ {
+ name: '合同附件',
+ value: '总部办公用品采购项目合同.pdf',
+ type: {
+ key: 'contractAnnex',
+ value: 'pdf',
+ },
+ },
+ {
+ name: '备注',
+ value: '--',
+ },
+ {
+ name: '创建时间',
+ value: '2020-12-22 10:00:00',
+ },
+ ];
+ }
+}
+
+export default new DetailBase();
diff --git a/src/service/service-detail-deploy.ts b/src/service/service-detail-deploy.ts
new file mode 100644
index 0000000..4b69eef
--- /dev/null
+++ b/src/service/service-detail-deploy.ts
@@ -0,0 +1,234 @@
+class DetailBase {
+ /**
+ * 下拉框选项数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getRadioOpetions() {
+ return [
+ {
+ label: 'Web',
+ value: 'Web',
+ },
+ {
+ label: 'Mobile',
+ value: 'Mobile',
+ },
+ ];
+ }
+
+ /**
+ * 弹窗数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getBaseInfoData() {
+ return [
+ {
+ name: '集群名',
+ value: 'helloworld',
+ },
+ {
+ name: '集群ID',
+ value: 'cls - 2ntelvxw',
+ type: {
+ key: 'color',
+ value: 'blue',
+ },
+ },
+ {
+ name: '状态',
+ value: '运行中',
+ type: {
+ key: 'color',
+ value: 'green',
+ },
+ },
+ {
+ name: 'K8S版本',
+ value: '1.7.8',
+ },
+ {
+ name: '配置',
+ value: '6.73 核 10.30 GB',
+ },
+ {
+ name: '所在地域',
+ value: '广州',
+ },
+ {
+ name: '新增资源所属项目',
+ value: '默认项目',
+ },
+ {
+ name: '节点数量',
+ value: '4 个',
+ },
+ {
+ name: '节点网络',
+ value: 'vpc - 5frmkm1x',
+ type: {
+ key: 'color',
+ value: 'blue',
+ },
+ },
+ {
+ name: '容器网络',
+ value: '172.16.0.0 / 16',
+ },
+ {
+ name: '集群凭证',
+ value: '显示凭证',
+ type: {
+ key: 'color',
+ value: 'blue',
+ },
+ },
+ {
+ name: '创建/更新',
+ value: '2018-05-31 22:11:44 2018-05-31 22:11:44',
+ type: {
+ key: 'contractAnnex',
+ value: 'pdf',
+ },
+ },
+ {
+ name: '描述',
+ value: 'istio_test',
+ },
+ ];
+ }
+
+ /**
+ * 表格定义基础数据
+ *
+ * @returns
+ *
+ * @memberOf DetailBase
+ */
+ getTableColumns() {
+ return [
+ {
+ minWidth: '448',
+ ellipsis: true,
+ colKey: 'name',
+ title: '项目名称',
+ sorter: (a, b) => a.name.substr(10) - b.name.substr(10),
+ },
+ {
+ width: '224',
+ ellipsis: true,
+ colKey: 'adminName',
+ title: '管理员',
+ },
+ {
+ width: '224',
+ ellipsis: true,
+ colKey: 'adminPhone',
+ title: '联系方式',
+ },
+ {
+ width: '224',
+ className: 'test',
+ ellipsis: true,
+ colKey: 'updateTime',
+ title: '创建时间',
+ sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
+ },
+ {
+ align: 'left',
+ width: '200',
+ className: 'test2',
+ ellipsis: true,
+ colKey: 'op',
+ fixed: 'right',
+ title: '操作',
+ },
+ ];
+ }
+
+ /**
+ * 获取弹窗配置数据
+ *
+ * @memberOf DetailBase
+ */
+ getPropUpData() {
+ const INITIAL_DATA = {
+ name: '',
+ warning: '',
+ success: '',
+ failB: '',
+ warningB: '',
+ loading: '',
+ add: '',
+ help: '',
+ };
+
+ return {
+ formData: { ...INITIAL_DATA },
+ courseOptions: [
+ { label: '语文', value: '1' },
+ { label: '数学', value: '2' },
+ { label: '英语', value: '3' },
+ ],
+ options: [
+ {
+ label: '资源初始化后',
+ value: 'beijing',
+ },
+ {
+ label: '上海',
+ value: 'shanghai',
+ },
+ ],
+ options1: [
+ {
+ label: '资源初始化后',
+ value: 'guangzhou',
+ },
+ {
+ label: '深圳',
+ value: 'shenzhen',
+ },
+ {
+ label: '东莞',
+ value: 'dongguang',
+ },
+ ],
+ options2: [
+ {
+ label: '资源初始化后',
+ value: 'nanjing',
+ },
+ {
+ label: '苏州',
+ value: '苏州',
+ },
+ {
+ label: '无锡',
+ value: 'wuxi',
+ },
+ ],
+ tSelectOptions: [
+ {
+ label: 'Sanzhang',
+ value: '1',
+ },
+ {
+ label: 'ls',
+ value: '2',
+ },
+ {
+ label: 'James',
+ value: '3',
+ },
+ ],
+ };
+ }
+}
+
+export default new DetailBase();
diff --git a/src/service/service-detail.ts b/src/service/service-detail.ts
new file mode 100644
index 0000000..7678bd4
--- /dev/null
+++ b/src/service/service-detail.ts
@@ -0,0 +1,57 @@
+interface DashboardPanel {
+ title: string;
+ number: string | number;
+ leftType?: string;
+ upTrend?: string;
+ downTrend?: string;
+}
+
+export const PANE_LIST_DATA: Array = [
+ {
+ title: '总申请数(次)',
+ number: '1126',
+ upTrend: '10%',
+ },
+ {
+ title: '供应商数量(个)',
+ number: '13',
+ downTrend: '13%',
+ },
+ {
+ title: '采购商品品类(类)',
+ number: '4',
+ upTrend: '10%',
+ },
+ {
+ title: '申请人数量(人)',
+ number: 90,
+ downTrend: '44%',
+ leftType: 'icon-file-paste',
+ },
+ {
+ title: '申请完成率(%)',
+ number: 80.5,
+ upTrend: '70%',
+ },
+ {
+ title: '到货及时率(%)',
+ number: 78,
+ upTrend: '16%',
+ },
+];
+export const PRODUCT_LIST = [
+ {
+ description: 'SSL证书又叫服务器证书,腾讯云为您提供证书的一站式服务,包括免费、付费证书的申请、管理及部',
+ index: 1,
+ isSetup: true,
+ name: 'SSL证书',
+ type: 4,
+ },
+ {
+ description: 'SSL证书又叫服务器证书,腾讯云为您提供证书的一站式服务,包括免费、付费证书的申请、管理及部',
+ index: 1,
+ isSetup: true,
+ name: 'SSL证书',
+ type: 4,
+ },
+];
diff --git a/src/service/service-user.ts b/src/service/service-user.ts
new file mode 100644
index 0000000..7fdc255
--- /dev/null
+++ b/src/service/service-user.ts
@@ -0,0 +1,64 @@
+export const USER_INFO_LIST = [
+ {
+ title: '手机',
+ content: '+86 13923734567',
+ },
+ {
+ title: '座机',
+ content: '734567',
+ },
+ {
+ title: '办公室邮箱',
+ content: 'Account@qq.com',
+ },
+ {
+ title: '座位',
+ content: 'T32F 012',
+ },
+ {
+ title: '管理主体',
+ content: '腾讯集团',
+ },
+ {
+ title: '直属上级',
+ content: 'Michael Wang',
+ },
+ {
+ title: '职位',
+ content: '高级 UI 设计师',
+ },
+ {
+ title: '入职时间',
+ content: '2021-07-01',
+ },
+ {
+ title: '所属团队',
+ content: '腾讯/腾讯公司/某事业群/某产品部/某运营中心/商户服务组',
+ span: 6,
+ },
+];
+
+export const TEAM_MEMBERS = [
+ {
+ avatar: 'https://avatars.githubusercontent.com/Wen1kang',
+ title: 'Lovellzhong 钟某某',
+ description: '直客销售 港澳拓展组员工',
+ },
+ {
+ avatar: 'https://avatars.githubusercontent.com/pengYYYYY',
+ title: 'Jiajingwang 彭某某',
+ description: '前端开发 前台研发组员工',
+ },
+ {
+ avatar: 'https://avatars.githubusercontent.com/u/24469546?s=96&v=4',
+ title: 'cruisezhang 林某某',
+ description: '技术产品 产品组员工',
+ },
+ {
+ avatar: 'https://avatars.githubusercontent.com/u/88708072?s=96&v=4',
+ title: 'Lovellzhang 商某某',
+ description: '产品运营 港澳拓展组员工',
+ },
+];
+
+export const PRODUCT_LIST = ['a', 'b', 'c', 'd'];
diff --git a/src/store/index.ts b/src/store/index.ts
new file mode 100644
index 0000000..b69e5be
--- /dev/null
+++ b/src/store/index.ts
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import user from './modules/user';
+import notification from './modules/notification';
+import setting from './modules/setting';
+import permission from './modules/permission';
+import tabRouter from './modules/tab-router'; // 多标签管理
+
+Vue.use(Vuex);
+
+const store = new Vuex.Store({
+ strict: import.meta.env.MODE === 'release',
+ modules: {
+ user,
+ setting,
+ notification,
+ permission,
+ tabRouter,
+ },
+});
+
+export default store;
diff --git a/src/store/modules/notification.ts b/src/store/modules/notification.ts
new file mode 100644
index 0000000..e42b808
--- /dev/null
+++ b/src/store/modules/notification.ts
@@ -0,0 +1,90 @@
+export interface msgDataItem {
+ id: string;
+ content: string;
+ type: string;
+ status: boolean;
+ collected: boolean;
+ date: string;
+ quality: string;
+}
+// 定义的state初始值
+const state: { msgData: Array } = {
+ msgData: [
+ {
+ id: '123',
+ content: '腾讯大厦一楼改造施工项目 已通过审核!',
+ type: '合同动态',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'high',
+ },
+ {
+ id: '124',
+ content: '三季度生产原材料采购项目 开票成功!',
+ type: '票务动态',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'low',
+ },
+ {
+ id: '125',
+ content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始,请提前10分钟前往 会议室1 进行签到!',
+ type: '会议通知',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'middle',
+ },
+ {
+ id: '126',
+ content: '一季度生产原材料采购项目 开票成功!',
+ type: '票务动态',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'low',
+ },
+ {
+ id: '127',
+ content: '二季度生产原材料采购项目 开票成功!',
+ type: '票务动态',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'low',
+ },
+ {
+ id: '128',
+ content: '三季度生产原材料采购项目 开票成功!',
+ type: '票务动态',
+ status: true,
+ collected: false,
+ date: '2021-01-01 08:00',
+ quality: 'low',
+ },
+ ],
+};
+
+const mutations = {
+ setMsgData(state, data) {
+ // eslint-disable-next-line no-param-reassign
+ state.msgData = data;
+ },
+};
+
+const getters = {
+ unreadMsg: (state) => state.msgData.filter((item) => item.status),
+ readMsg: (state) => state.msgData.filter((item) => !item.status),
+};
+
+const actions = {};
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+ getters,
+};
diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts
new file mode 100644
index 0000000..074353b
--- /dev/null
+++ b/src/store/modules/permission.ts
@@ -0,0 +1,66 @@
+import { resetRouter, asyncRouterList } from '@/router';
+
+function filterPermissionsRouters(routes, roles) {
+ const res = [];
+ routes.forEach((route) => {
+ const children = [];
+ route.children?.forEach((childRouter) => {
+ const roleCode = childRouter.meta?.roleCode || childRouter.name;
+ if (roles.indexOf(roleCode) !== -1) {
+ children.push(childRouter);
+ }
+ });
+ if (children.length > 0) {
+ route.children = children;
+ res.push(route);
+ }
+ });
+ return res;
+}
+
+const state = {
+ whiteListRouters: ['/login','/register'],
+ routers: [],
+};
+
+const mutations = {
+ setRouters: (state, routers) => {
+ state.routers = routers;
+ },
+};
+
+const getters = {
+ routers: (state) => state.routers,
+ whiteListRouters: (state) => state.whiteListRouters,
+};
+
+const actions = {
+ async initRoutes({ commit }, roles) {
+ let accessedRouters;
+
+ // special token
+ if (roles.includes('ALL_ROUTERS')) {
+ accessedRouters = asyncRouterList;
+ } else {
+ accessedRouters = filterPermissionsRouters(asyncRouterList, roles);
+ }
+
+ commit('setRouters', accessedRouters);
+
+ // register routers
+ // router.addRoutes(state.routers);
+ },
+ async restore({ commit }) {
+ // remove routers
+ resetRouter();
+ commit('setRouters', []);
+ },
+};
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+ getters,
+};
diff --git a/src/store/modules/setting.ts b/src/store/modules/setting.ts
new file mode 100644
index 0000000..5f6e2e9
--- /dev/null
+++ b/src/store/modules/setting.ts
@@ -0,0 +1,122 @@
+/* eslint-disable no-param-reassign */
+import { Color } from 'tvision-color';
+import STYLE_CONFIG from '@/config/style';
+import { TColorSeries, TColorToken, LIGHT_CHART_COLORS, DARK_CHART_COLORS } from '@/config/color';
+import { insertThemeStylesheet, generateColorMap } from '@/utils/color';
+
+// 定义的state初始值
+const state = {
+ ...STYLE_CONFIG,
+ showSettingPanel: false,
+ colorList: {},
+ chartColors: LIGHT_CHART_COLORS,
+};
+
+type IInitStateType = typeof state;
+
+export interface IStateType extends IInitStateType {
+ isAsideFooter: boolean;
+ showSettingPanel: boolean;
+}
+
+// 定义的state的初始值方法,传入state或者额外的方法,然后利用 vuex 的双向数据驱动进行值的改变
+// 可通过this.$store.commit(' ')调用,但是触发的是同步事件
+const mutations = {
+ update(state: IStateType, payload: IStateType) {
+ state.showBreadcrumb = payload.showBreadcrumb;
+ state.mode = payload.mode;
+ state.layout = payload.layout;
+ state.isSidebarCompact = payload.isSidebarCompact;
+ state.splitMenu = payload.splitMenu;
+ state.isFooterAside = payload.isFooterAside;
+ state.isSidebarFixed = payload.isSidebarFixed;
+ state.isHeaderFixed = payload.isHeaderFixed;
+ state.showHeader = payload.showHeader;
+ state.showFooter = payload.showFooter;
+ state.backgroundTheme = payload.backgroundTheme;
+ state.brandTheme = payload.brandTheme;
+ state.isUseTabsRouter = payload.isUseTabsRouter;
+ },
+ toggleSidebarCompact(state: IStateType) {
+ state.isSidebarCompact = !state.isSidebarCompact;
+ },
+ toggleUseTabsRouter(state: IStateType) {
+ state.isUseTabsRouter = !state.isUseTabsRouter;
+ },
+ showSidebarCompact(state: IStateType, payload: boolean) {
+ state.isSidebarCompact = payload;
+ },
+ toggleSettingPanel(state: IStateType, payload: boolean) {
+ state.showSettingPanel = payload;
+ },
+ addColor(state: IStateType, payload: TColorSeries) {
+ state.colorList = { ...state.colorList, ...payload };
+ },
+ changeChartColor(state: IStateType, payload: TColorToken) {
+ state.chartColors = { ...payload };
+ },
+};
+
+const getters = {
+ showHeader: (state: IStateType) => state.showHeader,
+ showSidebar: (state: IStateType) => state.layout !== 'top',
+ showSidebarLogo: (state: IStateType) => state.layout === 'side',
+ showHeaderLogo: (state: IStateType) => state.layout !== 'side',
+ showFooter: (state: IStateType) => state.showFooter,
+ isUseTabsRouter: (state: IStateType) => state.isUseTabsRouter,
+ mode: (state: IStateType) => {
+ if (state.mode === 'auto') {
+ const media = window.matchMedia('(prefers-color-scheme:dark)');
+ if (media.matches) {
+ return 'dark';
+ }
+ return 'light';
+ }
+ return state.mode;
+ },
+};
+
+const actions = {
+ changeTheme({ commit, dispatch }, payload: IStateType) {
+ dispatch('changeMode', payload);
+ dispatch('changeBrandTheme', payload);
+ commit('update', payload);
+ },
+ changeMode({ commit }, payload: IStateType) {
+ let theme = payload.mode;
+ if (payload.mode === 'auto') {
+ const media = window.matchMedia('(prefers-color-scheme:dark)');
+ if (media.matches) {
+ theme = 'dark';
+ } else {
+ theme = 'light';
+ }
+ }
+ const isDarkMode = theme === 'dark';
+
+ document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
+
+ commit('changeChartColor', isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS);
+ },
+ changeBrandTheme(_: { state: IStateType }, payload: IStateType) {
+ const { brandTheme, mode } = payload;
+ const { colors: newPalette, primary: brandColorIndex } = Color.getColorGradations({
+ colors: [brandTheme],
+ step: 10,
+ remainInput: false, // 是否保留输入 不保留会矫正不合适的主题色
+ })[0];
+ const colorMap = generateColorMap(brandTheme, newPalette, mode as 'light' | 'dark', brandColorIndex);
+
+ insertThemeStylesheet(brandTheme, colorMap, mode as 'light' | 'dark');
+
+ document.documentElement.setAttribute('theme-color', brandTheme);
+ },
+};
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+ getters,
+};
diff --git a/src/store/modules/tab-router.ts b/src/store/modules/tab-router.ts
new file mode 100644
index 0000000..f592c00
--- /dev/null
+++ b/src/store/modules/tab-router.ts
@@ -0,0 +1,83 @@
+export type TRouterInfo = {
+ path: string;
+ routeIdx: number;
+ title: string;
+ name?: string;
+ isAlive?: boolean;
+ isHome?: boolean;
+};
+
+export type TTabRouterType = {
+ isRefreshing: boolean;
+ tabRouterList: Array;
+};
+
+const homeRoute: Array = [
+ {
+ path: '/dashboard/base',
+ routeIdx: 0,
+ title: '仪表盘',
+ name: 'DashboardBase',
+ isHome: true,
+ },
+];
+
+const state: TTabRouterType = {
+ tabRouterList: homeRoute,
+ isRefreshing: false,
+};
+
+const mutations = {
+ // 处理刷新
+ toggleTabRouterAlive(state: TTabRouterType, routeIdx: number) {
+ state.isRefreshing = !state.isRefreshing;
+ state.tabRouterList[routeIdx].isAlive = !state.tabRouterList[routeIdx].isAlive;
+ },
+ // 处理新增
+ appendTabRouterList(state: TTabRouterType, newRoute: TRouterInfo) {
+ if (!state.tabRouterList.find((route: TRouterInfo) => route.path === newRoute.path))
+ // eslint-disable-next-line no-param-reassign
+ state.tabRouterList = state.tabRouterList.concat({ ...newRoute, isAlive: true });
+ },
+ // 处理关闭当前
+ subtractCurrentTabRouter(state: TTabRouterType, newRoute: TRouterInfo) {
+ const { routeIdx } = newRoute;
+ state.tabRouterList = state.tabRouterList.slice(0, routeIdx).concat(state.tabRouterList.slice(routeIdx + 1));
+ },
+ // 处理关闭右侧
+ subtractTabRouterBehind(state: TTabRouterType, newRoute: TRouterInfo) {
+ const { routeIdx } = newRoute;
+ state.tabRouterList = state.tabRouterList.slice(0, routeIdx + 1);
+ },
+ // 处理关闭左侧
+ subtractTabRouterAhead(state: TTabRouterType, newRoute: TRouterInfo) {
+ const { routeIdx } = newRoute;
+ state.tabRouterList = homeRoute.concat(state.tabRouterList.slice(routeIdx));
+ },
+ // 处理关闭其他
+ subtractTabRouterOther(state: TTabRouterType, newRoute: TRouterInfo) {
+ const { routeIdx } = newRoute;
+ state.tabRouterList = homeRoute.concat([state.tabRouterList?.[routeIdx]]);
+ },
+ removeTabRouterList() {
+ state.tabRouterList = [];
+ },
+ initTabRouterList(state: TTabRouterType, newRoute: TRouterInfo[]) {
+ state.tabRouterList = newRoute;
+ },
+};
+
+const getters = {
+ tabRouterList: (state: TTabRouterType) => state.tabRouterList,
+ isRefreshing: (state: TTabRouterType) => state.isRefreshing,
+};
+
+const actions = {};
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+ getters,
+};
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
new file mode 100644
index 0000000..c18b6e5
--- /dev/null
+++ b/src/store/modules/user.ts
@@ -0,0 +1,88 @@
+const InitUserInfo = {
+ roles: [],
+};
+
+// 定义的state初始值
+const state = {
+ token: localStorage.getItem('associationToken') || 'main_token', // 默认token不走权限
+ userInfo: InitUserInfo,
+ association:localStorage.getItem('associationInfo') || '',
+ apiUrl:'http://192.168.3.130'
+};
+
+const mutations = {
+ setToken(state, token) {
+ localStorage.setItem('associationToken', token);
+ state.token = token;
+ },
+ removeToken(state) {
+ localStorage.removeItem('associationToken');
+ state.token = '';
+ },
+ setUserInfo(state, userInfo) {
+ state.userInfo = userInfo;
+ },
+ setAssociation(state, Association) {
+ localStorage.setItem('associationInfo', JSON.stringify(Association) );
+ state.association = Association;
+ },
+ removeAssociation(state) {
+ localStorage.removeItem('associationInfo');
+ state.association = '';
+ },
+};
+
+const getters = {
+ token: (state) => state.token,
+ roles: (state) => state.userInfo?.roles,
+};
+
+const actions = {
+ async login({ commit }, userInfo) {
+ const mockLogin = async (userInfo) => {
+ // 登录请求流程
+ console.log(userInfo);
+ commit('setAssociation',userInfo[0]);
+ return{
+ code: 200,
+ }
+ };
+
+ const res = await mockLogin(userInfo);
+ if (res.code === 200) {
+ commit('setToken', 'main_token');
+ } else {
+ return res;
+ }
+ },
+ async getUserInfo({ commit, state }) {
+ const mockRemoteUserInfo = async (token) => {
+ if (token === 'main_token') {
+ return {
+ name: 'td_main',
+ roles: ['ALL_ROUTERS'],
+ };
+ }
+ return {
+ name: 'td_dev',
+ roles: ['UserIndex', 'DashboardBase', 'login'],
+ };
+ };
+
+ const res = await mockRemoteUserInfo(state.token);
+
+ commit('setUserInfo', res);
+ },
+ async logout({ commit }) {
+ commit('removeToken');
+ commit('setUserInfo', InitUserInfo);
+ },
+};
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions,
+ getters,
+};
diff --git a/src/style/font-family.less b/src/style/font-family.less
new file mode 100644
index 0000000..c639e25
--- /dev/null
+++ b/src/style/font-family.less
@@ -0,0 +1,6 @@
+@font-face {
+ font-family: 'TencentSansW7';
+ src: url('data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAusAA4AAAAAEJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAALkAAAABwAAAAchqPqzUdERUYAAAtwAAAAHgAAAB4AKQAbT1MvMgAAAbgAAABZAAAAYGmceoNjbWFwAAACYAAAAJcAAAHsPmfPZmdhc3AAAAtkAAAADAAAAAwACAAbZ2x5ZgAAAywAAAW8AAAG/Ivn/ztoZWFkAAABRAAAADYAAAA2E+AL5GhoZWEAAAF8AAAAIAAAACQIawJ9aG10eAAAAhQAAABMAAAATCG/Auxsb2NhAAADAAAAACwAAAAsDjIQIm1heHAAAAGcAAAAGgAAACAAfgBDbmFtZQAACOgAAAIUAAAEm0zGvtJwb3N0AAAK/AAAAGYAAAB/4wuGdnByZXAAAAL4AAAACAAAAAhwAgESAAEAAAABBR/xlpGAXw889QALA+gAAAAA2Ac3gwAAAADY+IxB//L/HAPPAwAAAAAIAAIAAAAAAAB42mNgZGBgWf7vFAMD84v/n/7vZD7PABRBAYIAwxQH7XjaY2BkYGAQZXBiYGEAAUYGGEiBUAAMEQDCAAB42mNgYepm2sPAysDA1MUUwcDA4A2hGeMYjBjNgKI8HMxMTCz8TCwLGJj2CzCAgRiI8PX382d0YGBMEmQ2+u/FcIJlOVA9CwMjSI6JlekwkFJgYAQAR1kL+QAAAAJYAHYAAAAAAU0AAAEEAAACUAAhAlYAFQJUACACKgAdAZUANgEUABUBYAAkA5wAFQINABsBqAA0AnAAKgJYACoD6ACF//YANP/yACN42mNgYGBmgGAZBkYGEHgG5DGC+SwMp4C0HIMAUISPQYEhiSGNIZMhl6GUoZJhgeIkfS6/N4GpQQuSBP//B+tMZEgByucwFGOT/7/4/6L/C/7P+z/z/7T/yffqLrJvVFu3Zm3xPJBtcgz4ADPFkIGRDWgMIcBAIWBhZWBj52Bg4GRg4OIGi/Dw8gFJfgYqA/JcCgA99Se8ALgB/4W4AAGNAAAAFAAUABQAFABSAIIAsgD6ASIBOAFYAYIBxgHwAhQCRAJaAogCygMYA3542k1Ua2xTZRj+LmtP23Vdz2lPz3pZb2dr1+u2nq2H0d3Z2OhI5mC4AZMBo0gM98E0oRn1AqgoIYDG4BAkakDkJ4iyiCZGAiISUH8YjIQfEhNUMCoJrme+bTfkx/nxveec53ne533eDxE0Nn0V/0V2I4oYhATWw1ZKrDiGx5Vfzp6NkXPZ7mH8ECGCPNNXiZWokANVIYRjFt7MUI83iuvrWnAzTWA5Xl/nC2G/SZJFr7oUq3mzBaf7F5S0Kt+F59i1aq0j0tbwJmXcwUtsz3HHhEtQaYr0RFUbL0sqB8yRClvcG2uwa7hKg4VLKdFjZmeEN5SwwM0Dd4DcRaXAXuAuxQYqekwSIxRoqRRrxjLevrK/RNCUhXt7lYevpQMf6StjW1sz/gCrIqqm+Z7krsjCmJU67/zexrvMykE+CniA7wb8oUf4EhW9vtm2qGQSvQY808+t9Ov/5ih0zlhfyytfbGodd/ht2rJiH7k7dTtP0NQTYpUo3qDzSnsSVpc5j18O+DzRIzeqyel34nwDOISZHGoCM6I3SvKMRJppKM8pxeIy3tbU4S4y6Oc231Sp3OFLgXMV7dV2xq8L9K9IUZvY5XAZi4wfms2U6K21PoHvnVfvchitXEorhH2O4K253RUTnIYt0Xv4ITanB6M4zPwm9GuBQ4GIEaloEmVJzvXM4JeqXaxWfYg7tCi9qIddqNZZg53yKEv2lLgkEWaDr6fERHfEnEL5/mA+uJzcLmTIJEsMNUl0t5AR7o+kR8jqTCa7nsjZS3nuCvg2DtwcpC3ftQzfgg1ODMRfBjt8eiP8ZLAE7HNDsRJPUKhYTmqy13osvJGm4H/gomsgh8Ksk2oGpM+kAHqAh0wmuitpSWO6SWer2NOX7vu8D2SouFCACSSVk3hgjmBllRp8Takhck6THTT9DZjVoMkPprfgmSE8igHzKNOJ//MX4X4rN6m0VF022lan02g4R11DNngDahqoPQe1YoZ31SRiKWN5fammqNgddMiRcNheAoXIbKGlKsoXo7w3daDjFDmNbOAiM+uJOONSbjoSIzEPI1owpyO0oL6twlAcSbI9zrTzKIePTdeaeZamOHe4zJtA06kTJ3J+BSF7vdCbKZ/swsbGZzyHZvCN9BrlzmN+vUVU2UsFq/CAcjJnVV5bcNpB2gCnPI9jILDquZ1rwflleQzwqx1ri8PJzh+4K3GnUcPsg32pSdfAJmYA+dPm+a61rBj0N3Z5ktio3Gu1uAqZ3IVW0R2Ar4GDwIiyp97jJ5MXLuzbn71IGvYT1fXrR545kvdp+p/pNB0nvyI7QiqR+A2UEZupLPmjOK/KIlg4On741U6xf3hj49Ha0e2bov3tVFd6oOx2uVvb9dlLeOTjxt1797XUvDBx+snTOv1Sk/2y0g7YRTCDNP2WIqSHhLqQCHQGnEuYmpHhhvFYBNHnV8UsUPJLpjjwYZNA8ZC+yv7Uxu5QiG/vMWOfNzzq9uH7XqFoyz3byRWUv1ClnNowsoqi+CYp248fhN0TC94YXrSkYyRod03dWkYOmpdOfUAetGWTiE7/CRomQYML+VG0kHOG5AjjpjjE0kAYMc7JubMsqZnK3GvqMQmNOHcR4u9t5Woai31t3xXxYVrcaZQXt+5cOWZZV7ZXp94Io6u1C5Q+rZzY+pP62YEdZEmpx6QcUb4ZnMJ2nXbs2uWtb+P57w6sSoYytQYnl62juhVEnT1e2HURtF0EbQnUBsrAD9AADglwhfgLHkWxX2TiMqPOeyQzftinXHjhbVwuJVIdiOY9fvBRstDzyh9Ys6B6W2h0HnvO85DbvMsa2xJhNPgiPzBkaN4W/NF+0PaOd/ug7Yz+DNfVp3/v5+Jx8yRdT3F5dLMorLXik6PrnhhYfKAxM/hyb0Oanycm3+86bHMPC6JyZfB8YJnN8sngi4xqqdq3nN0//vzOTNXq5YsR+g8984WfeNq1Us1qFEEQ/npnk0X8IQGJIjnUSRLYLLt7MMlFCHvNKRvMuTPTmZ1kdib0zAY3ePMFfAAvigi5+Ry+gA8iiOLFr3tbTFZWcnGgu76qrvqqpqoAPMQ3KMy+A3wMWOGBehRwAy31LOAIayoPuEmfdwEv4Z76HPAy7quvAbfwqvEz4BXcjd4EvIpG9J5sqnmH2gfP7LDCOn4E3CD/04AjtNXzgJtYV68DXsJj9SngZTxRXwJu4XtDBbyCtehlwKtoRm8xQIlzTGGRIcUINQRXPH100cMOtgLape0QBgVif9dBjxlTkCPnSckj2MCQNudzGeQmrS5PB22ifcYmxII9RuWUf3JXXjOUhvKCt/PEoDyf2iwd1XIl/W5vZ4vXrhyaIjZFTRmPijIv06lsDEemuOTZlEHZact+nXRkL8/FR1diTWXshUnIefNnhtCULv0Rtvk4ox7qopKjbbcNhhVOWK1mXTgw6STX9t8kMh91k1RuRfJXJS98Zyp2rKSbcDIdzqfPB2OrrCyk1+n2F3HOMzrC+aFmPrcOg0i9XvukbhhCbPmaUBv73zqjrcTJf1gPV7PL6PK4yGN6L6oq882IvaWm/0w/ZfOt9014x3yZta1yS/V7fbJKNBcjzaraWJNIbXVixtqeSXly6x3TRSJjPZVjc50qKyQ2ttaUpxObVUkW15xRtXD9rg8Hs3FxRr8ATJnl93jaY2BiAIP/zQxGDNiAKBAzMjAxMjG4MLgyuDN4MHgy+DD4MwQwhDGEM0QwxDAyM7IwsjKyMbKzl+ZlGhgYGHIlFhXllxdlpmeUgISM3AwcQbSJq6sziDY1cjQA0WZGhoYAgBwU3AAAAAEAAgAIAAr//wAPAAEAAAAMAAAAFgAAAAIAAQADABQAAQAEAAAAAgAAAAAAAAABAAAAANWkJwgAAAAA2Ac3gwAAAADY+IxB') format('woff');
+ font-weight: normal;
+ font-style: normal;
+}
diff --git a/src/style/index.less b/src/style/index.less
new file mode 100644
index 0000000..7717225
--- /dev/null
+++ b/src/style/index.less
@@ -0,0 +1,5 @@
+@import './variables.less';
+
+@import './font-family.less';
+
+@import './reset.less';
diff --git a/src/style/layout.less b/src/style/layout.less
new file mode 100644
index 0000000..9a99ca6
--- /dev/null
+++ b/src/style/layout.less
@@ -0,0 +1,201 @@
+@import './variables.less';
+@import './font-family.less';
+
+// layout rewrite
+
+.t-layout__sider {
+ width: fit-content;
+}
+
+.t-layout__header {
+ height: auto;
+}
+
+.t-layout.t-layout--with-sider {
+ > .t-layout {
+ flex: 1;
+ min-width: 760px;
+ }
+}
+
+.t-layout.t-layout--with-sider {
+ > .t-layout__content {
+ flex: 1;
+ min-width: 760px;
+ }
+}
+
+.t-menu--dark .t-menu__operations .t-icon {
+ color: rgba(255, 255, 255, 0.55);
+ &:hover {
+ cursor: pointer;
+ }
+}
+.t-default-menu.t-menu--dark {
+ background: var(--td-gray-color-13);
+}
+.t-default-menu:not(.t-menu--dark) .t-menu__item.t-is-active:not(.t-is-opened) {
+ background-color: var(--td-brand-color-1);
+ color: var(--td-brand-color);
+ .t-icon {
+ color: var(--td-brand-color);
+ }
+}
+
+.t-alert--info {
+ background-color: var(--td-brand-color-1);
+}
+
+.@{starter-prefix} {
+ // 布局元素调整
+ &-wrapper {
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ &-main-wrapper {
+ height: 500px;
+ overflow: scroll;
+ }
+
+ &-side-nav-layout {
+ &-relative {
+ height: 100%;
+ }
+ }
+
+ &-content-layout {
+ padding: var(--td-comp-paddingTB-xl) var(--td-comp-paddingLR-xl);
+ }
+
+ &-layout {
+ height: calc(100vh - var(--td-comp-size-xxxl));
+ overflow-y: scroll;
+
+ &-tabs-nav {
+ max-width: 100%;
+ position: fixed;
+ overflow: visible;
+ z-index: 100;
+ }
+ &-tabs-nav + .@{starter-prefix}-content-layout {
+ padding-top: var(--td-comp-paddingTB-xl);
+ }
+
+ &::-webkit-scrollbar {
+ width: 8px;
+ background: transparent;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ border-radius: 6px;
+ border: 2px solid transparent;
+ background-clip: content-box;
+ background-color: var(--td-scrollbar-color);
+ }
+ }
+
+ &-footer-layout {
+ padding: 0;
+ margin-bottom: var(--td-comp-margin-l);
+ }
+
+ // slideBar
+ &-sidebar-layout {
+ height: 100%;
+ }
+
+ &-sidebar-compact {
+ width: var(--td-comp-size-xxxl);
+ }
+
+ &-sidebar-layout-side {
+ z-index: 100;
+ }
+
+ &-side-nav {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ z-index: 200;
+ transition: all 0.3s;
+ min-height: 100%;
+
+ &-mix {
+ top: var(--td-comp-size-xxxl);
+
+ &-fixed {
+ top: var(--td-comp-size-xxxl);
+ z-index: 0;
+ }
+ }
+
+ &-no-fixed {
+ position: relative;
+ z-index: 1;
+ }
+
+ &-no-logo {
+ z-index: 1;
+ }
+
+ &-logo-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ &-logo-t-logo {
+ height: 32px;
+ width: 100%;
+ }
+
+ &-logo-tdesign-logo {
+ padding: 0 24px;
+ height: 32px;
+ width: 100%;
+ color: var(--td-text-color-primary);
+ }
+
+ &-logo-normal {
+ color: var(--td-brand-color);
+ font: var(--td-font-body-large);
+ transition: all 0.3s;
+ }
+ }
+
+ &-side-nav-placeholder {
+ flex: 1 1 232px;
+ min-width: 232px;
+ transition: all 0.3s;
+
+ &-hidden {
+ flex: 1 1 72px;
+ min-width: 72px;
+ transition: all 0.3s;
+ }
+ }
+}
+
+.route-tabs-dropdown {
+ .t-icon {
+ margin-right: 8px;
+ }
+}
+
+.logo-container {
+ cursor: pointer;
+ display: inline-flex;
+ height: var(--td-comp-size-xxxl);
+ margin-left: 24px;
+}
+
+.version-container {
+ color: var(--td-text-color-primary);
+ opacity: 0.4;
+}
diff --git a/src/style/reset.less b/src/style/reset.less
new file mode 100644
index 0000000..f1e97fe
--- /dev/null
+++ b/src/style/reset.less
@@ -0,0 +1,78 @@
+body {
+ color: var(--td-text-color-secondary);
+ font-family: -apple-system, BlinkMacSystemFont, PingFang SC, Microsoft YaHei, Arial Regular;
+ font: var(--td-font-body-medium);
+ -webkit-font-smoothing: antialiased;
+ padding: 0;
+ margin: 0;
+}
+
+pre {
+ font-family: var(--td-font-family);
+}
+
+ul,
+dl,
+li,
+dd,
+dt {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+figure,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p {
+ margin: 0;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+.t-button-link,
+a {
+ color: var(--td-brand-color);
+ text-decoration: none;
+ margin-right: var(--td-comp-margin-xxl);
+ cursor: pointer;
+ transition: color @anim-duration-base @anim-time-fn-easing;
+
+ &:hover {
+ color: var(--td-brand-color-hover);
+ }
+
+ &:active {
+ color: var(--td-brand-color-active);
+ }
+
+ &--active {
+ color: var(--td-brand-color-active);
+ }
+
+ &:focus {
+ text-decoration: none;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+}
+
+.container-base-margin-top {
+ margin-top: 16px;
+}
+
+.card-date-picker-container {
+ width: 250px;
+}
diff --git a/src/style/variables.less b/src/style/variables.less
new file mode 100644
index 0000000..5c75320
--- /dev/null
+++ b/src/style/variables.less
@@ -0,0 +1,27 @@
+/** 公共前缀 */
+@starter-prefix: tdesign-starter;
+
+// 颜色、尺寸、阴影、圆角、字体 variables 请参考 https://tdesign.tencent.com/starter/docs/vue/design-token
+
+// 响应式断点
+@screen-sm: 768px;
+@screen-md: 992px;
+@screen-lg: 1200px;
+@screen-xl: 1400px;
+
+@screen-sm-min: @screen-sm;
+@screen-md-min: @screen-md;
+@screen-lg-min: @screen-lg;
+@screen-xl-min: @screen-xl;
+
+@screen-sm-max: (@screen-md-min - 1px);
+@screen-md-max: (@screen-lg-min - 1px);
+@screen-lg-max: (@screen-xl-min - 1px);
+
+// 动画
+@anim-time-fn-easing: cubic-bezier(0.38, 0, 0.24, 1);
+@anim-time-fn-ease-out: cubic-bezier(0, 0, 0.15, 1);
+@anim-time-fn-ease-in: cubic-bezier(0.82, 0, 1, 0.9);
+@anim-duration-base: 0.2s;
+@anim-duration-moderate: 0.24s;
+@anim-duration-slow: 0.28s;
diff --git a/src/utils/charts.ts b/src/utils/charts.ts
new file mode 100644
index 0000000..9c67eb4
--- /dev/null
+++ b/src/utils/charts.ts
@@ -0,0 +1,38 @@
+import dayjs from 'dayjs';
+
+/**
+ * @export
+ * @param {string[]} dateTime
+ * @param {number} divideNum
+ * @returns {string[]}
+ */
+export function getDateArray(dateTime: string[] = [], divideNum = 10): string[] {
+ const timeArray: string[] = [];
+ if (dateTime.length > 0) {
+ for (let i = 0; i < divideNum; i++) {
+ const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
+ const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
+ timeArray.push(dayjs(enhandTime).format('YYYY-MM-DD'));
+ }
+ }
+
+ return timeArray;
+}
+
+/**
+ * 获取随机数
+ *
+ * @param {number} [num=100]
+ * @returns
+ *
+ * @memberOf DashboardBase
+ */
+export function getRandomArray(num = 100): number {
+ let resultNum = Number((Math.random() * num).toFixed(0));
+
+ if (resultNum <= 1) {
+ resultNum = 1;
+ }
+
+ return resultNum;
+}
diff --git a/src/utils/color.ts b/src/utils/color.ts
new file mode 100644
index 0000000..92d5beb
--- /dev/null
+++ b/src/utils/color.ts
@@ -0,0 +1,118 @@
+import { Color } from 'tvision-color';
+import * as echarts from 'echarts/core';
+import trim from 'lodash/trim';
+import { TColorToken } from '@/config/color';
+
+/**
+ * 依据主题类型获取颜色
+ *
+ * @export
+ * @param {string} theme
+ * @returns {}
+ */
+export function getColorFromTheme(): Array {
+ const theme = trim(getComputedStyle(document.documentElement).getPropertyValue('--td-brand-color'));
+ const themeColorList = Color.getRandomPalette({
+ color: theme,
+ colorGamut: 'bright',
+ number: 8,
+ });
+
+ return themeColorList;
+}
+
+/** 图表颜色 */
+export function getChartListColor(): Array {
+ const res = getColorFromTheme();
+
+ return res;
+}
+
+/**
+ * 更改图表主题颜色
+ *
+ * @export
+ * @param {Array} chartsList
+ * @param {string} theme
+ */
+export function changeChartsTheme(chartsList: echarts.EChartsType[]): void {
+ if (chartsList && chartsList.length) {
+ const chartChangeColor = getChartListColor();
+
+ for (let index = 0; index < chartsList.length; index++) {
+ const elementChart = chartsList[index];
+
+ if (elementChart) {
+ const optionVal = elementChart.getOption();
+
+ // 更改主题颜色
+ optionVal.color = chartChangeColor;
+
+ elementChart.setOption(optionVal, true);
+ }
+ }
+ }
+}
+
+/**
+ * 根据当前主题色、模式等情景 计算最后生成的色阶
+ */
+export function generateColorMap(
+ theme: string,
+ colorPalette: Array,
+ mode: 'light' | 'dark',
+ brandColorIdx: number,
+) {
+ const isDarkMode = mode === 'dark';
+
+ if (isDarkMode) {
+ // eslint-disable-next-line no-use-before-define
+ colorPalette.reverse().map((color) => {
+ const [h, s, l] = Color.colorTransform(color, 'hex', 'hsl');
+ return Color.colorTransform([h, Number(s) - 4, l], 'hsl', 'hex');
+ });
+ brandColorIdx = 5;
+ colorPalette[0] = `${colorPalette[brandColorIdx]}20`;
+ }
+
+ const colorMap = {
+ '--td-brand-color': colorPalette[brandColorIdx], // 主题色
+ '--td-brand-color-1': colorPalette[0], // light
+ '--td-brand-color-2': colorPalette[1], // focus
+ '--td-brand-color-3': colorPalette[2], // disabled
+ '--td-brand-color-4': colorPalette[3],
+ '--td-brand-color-5': colorPalette[4],
+ '--td-brand-color-6': colorPalette[5],
+ '--td-brand-color-7': brandColorIdx > 0 ? colorPalette[brandColorIdx - 1] : theme, // hover
+ '--td-brand-color-8': colorPalette[brandColorIdx], // 主题色
+ '--td-brand-color-9': brandColorIdx > 8 ? theme : colorPalette[brandColorIdx + 1], // click
+ '--td-brand-color-10': colorPalette[9],
+ };
+ return colorMap;
+}
+
+/**
+ * 将生成的样式嵌入头部
+ */
+export function insertThemeStylesheet(theme: string, colorMap: TColorToken, mode: 'light' | 'dark') {
+ const isDarkMode = mode === 'dark';
+ const root = !isDarkMode ? `:root[theme-color='${theme}']` : `:root[theme-color='${theme}'][theme-mode='dark']`;
+
+ const styleSheet = document.createElement('style');
+ styleSheet.type = 'text/css';
+ styleSheet.innerText = `${root}{
+ --td-brand-color: ${colorMap['--td-brand-color']};
+ --td-brand-color-1: ${colorMap['--td-brand-color-1']};
+ --td-brand-color-2: ${colorMap['--td-brand-color-2']};
+ --td-brand-color-3: ${colorMap['--td-brand-color-3']};
+ --td-brand-color-4: ${colorMap['--td-brand-color-4']};
+ --td-brand-color-5: ${colorMap['--td-brand-color-5']};
+ --td-brand-color-6: ${colorMap['--td-brand-color-6']};
+ --td-brand-color-7: ${colorMap['--td-brand-color-7']};
+ --td-brand-color-8: ${colorMap['--td-brand-color-8']};
+ --td-brand-color-9: ${colorMap['--td-brand-color-9']};
+ --td-brand-color-10: ${colorMap['--td-brand-color-10']};
+ }`;
+
+ document.head.appendChild(styleSheet);
+}
diff --git a/src/utils/date.ts b/src/utils/date.ts
new file mode 100644
index 0000000..bbfa47a
--- /dev/null
+++ b/src/utils/date.ts
@@ -0,0 +1,12 @@
+// 获取常用时间
+import dayjs from 'dayjs';
+
+export const LAST_7_DAYS = [
+ dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
+ dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
+];
+
+export const LAST_30_DAYS = [
+ dayjs().subtract(30, 'day').format('YYYY-MM-DD'),
+ dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
+];
diff --git a/src/utils/request.ts b/src/utils/request.ts
new file mode 100644
index 0000000..ed0ea89
--- /dev/null
+++ b/src/utils/request.ts
@@ -0,0 +1,66 @@
+import axios from 'axios';
+import store from '../store'
+//const API_HOST = env === 'mock' ? '/' : proxy[env].API; // 如果是mock模式 就不配置host 会走本地Mock拦截
+const API_HOST ="/api/";
+const CODE = {
+ LOGIN_TIMEOUT: 100000,
+ REQUEST_SUCCESS: 0,
+ REQUEST_FOBID: 1001,
+};
+
+const instance = axios.create({
+ baseURL: API_HOST,
+ timeout: 10000,
+ withCredentials: true,
+});
+
+// eslint-disable-next-line
+// @ts-ignore
+// axios的retry ts类型有问题
+instance.interceptors.retry = 3;
+
+instance.interceptors.request.use((config) => {
+ // 在原有配置基础上添加新参数
+ console.log(store.state.user.association);
+ if(store.state.user.association){
+ if(typeof (store.state.user.association)=='object'){
+ var association=store.state.user.association;
+ }else{
+ var association=JSON.parse(store.state.user.association);
+ }
+ config.data = { ...config.data, association_id: association.id };
+ }
+
+ console.log(config.data);
+ return config;
+});
+
+instance.interceptors.response.use(
+ (response) => {
+ const { data } = response;
+ return data;
+ },
+ (err) => {
+ const { config } = err;
+
+ if (!config || !config.retry) return Promise.reject(err);
+
+ config.retryCount = config.retryCount || 0;
+
+ if (config.retryCount >= config.retry) {
+ return Promise.reject(err);
+ }
+
+ config.retryCount += 1;
+
+ const backoff = new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({});
+ }, config.retryDelay || 1);
+ });
+
+ return backoff.then(() => instance(config));
+ },
+);
+
+export default instance;
diff --git a/stylelint.config.js b/stylelint.config.js
new file mode 100644
index 0000000..1df359c
--- /dev/null
+++ b/stylelint.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ defaultSeverity: 'error',
+ extends: ['stylelint-config-prettier'],
+ plugins: ['stylelint-less'],
+};
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..b803498
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "es2015",
+ "module": "esnext",
+ "lib": ["esnext", "dom"],
+ "allowJs": true,
+ "checkJs": false,
+ "noImplicitAny": false,
+ "isolatedModules": false,
+ "experimentalDecorators": true,
+ "esModuleInterop": true,
+ "noImplicitThis": false,
+ "strictNullChecks": false,
+ "skipLibCheck": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "jsx": "preserve",
+ "noEmit": true,
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["**/*.ts", "**/*.tsx"],
+ "compileOnSave": false
+}
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..7752d70
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,59 @@
+import { loadEnv } from 'vite';
+import { viteMockServe } from 'vite-plugin-mock';
+import { createVuePlugin } from 'vite-plugin-vue2';
+import { createSvgPlugin } from 'vite-plugin-vue2-svg';
+
+import path from 'path';
+
+const CWD = process.cwd();
+
+export default ({ mode }) => {
+ const { VITE_BASE_URL } = loadEnv(mode, CWD);
+
+ return {
+ base: VITE_BASE_URL,
+ resolve: {
+ alias: {
+ '~': path.resolve(__dirname, './'),
+ '@': path.resolve(__dirname, './src'),
+ },
+ },
+
+ css: {
+ preprocessorOptions: {
+ less: {
+ modifyVars: {},
+ },
+ },
+ },
+
+ plugins: [
+ createVuePlugin({
+ jsx: true,
+ }),
+ viteMockServe({
+ mockPath: 'mock',
+ localEnabled: true,
+ }),
+ createSvgPlugin(),
+ ],
+
+ build: {
+ cssCodeSplit: false,
+ },
+
+ server: {
+ proxy: {
+ '/api': {
+ // 用于开发环境下的转发请求
+ // 更多请参考:https://vitejs.dev/config/#server-proxy
+ target: 'http://192.168.3.130/',
+ pathRewrite: {
+ '^/api': ''
+ },
+ changeOrigin: true,
+ },
+ },
+ },
+ };
+};