mirror of
https://github.com/Tencent/tdesign-vue-next-starter.git
synced 2024-11-10 13:01:14 +08:00
Merge branch 'develop' of github.com:Tencent/tdesign-vue-next-starter into main
This commit is contained in:
commit
f8a2999f98
120
README-zh_CN.md
Normal file
120
README-zh_CN.md
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
|
||||||
|
<p style="display:flex; justify-content: center">
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://tdesign.tencent.com/starter/vue-next/#/dashboard/base" target="_blank">
|
||||||
|
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/starter/brand-logo.svg">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://nodejs.org/en/about/releases/"><img src="https://img.shields.io/node/v/vite.svg" alt="node compatility"></a>
|
||||||
|
<a href="https://github.com/Tencent/tdesign-vue-next/blob/develop/LICENSE">
|
||||||
|
<img src="https://img.shields.io/npm/l/tdesign-vue-next.svg?sanitize=true" alt="License">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
简体中文 | [English](./README.md)
|
||||||
|
|
||||||
|
### 项目简介
|
||||||
|
|
||||||
|
TDesign Vue Next Starter 是一个基于 TDesign,使用 `Vue3`、`Vite2`、`Pinia`、`TypeScript` 开发,可进行个性化主题配置,旨在提供项目开箱即用的、配置式的中后台项目。
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="http://tdesign.tencent.com/starter/vue-next/">在线预览</a>
|
||||||
|
·
|
||||||
|
<a href="https://tdesign.tencent.com/starter/">使用文档</a>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<img src="docs/starter.png">
|
||||||
|
|
||||||
|
### 特性
|
||||||
|
|
||||||
|
- 内置多种常用的中后台页面
|
||||||
|
- 完善的目录结构
|
||||||
|
- 完善的代码规范配置
|
||||||
|
- 支持暗黑模式
|
||||||
|
- 自定义主题颜色
|
||||||
|
- 多种空间布局
|
||||||
|
- 内置 Mock 数据方案
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
|
||||||
|
> 通过 `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-next-starter/issues/new/choose) 或者提交 [Pull Request](https://github.com/Tencent/tdesign-vue-next-starter/pulls)。
|
||||||
|
|
||||||
|
#### Pull Request
|
||||||
|
|
||||||
|
1. Fork 代码!
|
||||||
|
2. 创建自己的分支: `git checkout -b feat/xxxx`
|
||||||
|
3. 提交你的修改: `git commit -a 'feat(project): describe'`
|
||||||
|
4. 推送您的分支: `git push origin feat/xxxx`
|
||||||
|
5. 提交 `pull request`
|
||||||
|
|
||||||
|
#### 贡献提交规范
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
|
### 兼容性
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
|
||||||
|
|
||||||
|
### 开源协议
|
||||||
|
|
||||||
|
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-vue-next-starter/LICENSE)。
|
||||||
|
|
92
README.md
92
README.md
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<p style="display:flex; justify-content: center">
|
<p style="display:flex; justify-content: center">
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
@ -15,104 +14,85 @@
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
### 项目简介
|
English | [简体中文](./README-zh_CN.md)
|
||||||
|
### Introduction
|
||||||
|
|
||||||
TDesign Vue Next Starter 是一个基于 TDesign,使用 `Vue3`、`Vite2`、`Pinia`、`TypeScript` 开发,可进行个性化主题配置,旨在提供项目开箱即用的、配置式的中后台项目。
|
TDesign Vue Next Starter is a TDesign-based developed with `Vue3`, `Vite2`, `Pinia`, `TypeScript`. It can be customized theme configuration, and aims to provide project out-of-the-box, configuration-style middle and background projects.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="http://tdesign.tencent.com/starter/vue-next/">在线预览</a>
|
<a href="http://tdesign.tencent.com/starter/vue-next/">Live Preview</a>
|
||||||
·
|
·
|
||||||
<a href="https://tdesign.tencent.com/starter/">使用文档</a>
|
<a href="https://tdesign.tencent.com/starter/">Documentation</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<img src="docs/starter.png">
|
<img src="docs/starter.png">
|
||||||
|
|
||||||
### 特性
|
### Features
|
||||||
|
|
||||||
- 内置多种常用的中后台页面
|
- Various provided pages for develop
|
||||||
- 完善的目录结构
|
- Complete directory structure for develop
|
||||||
- 完善的代码规范配置
|
- Code specification configuration
|
||||||
- 支持暗黑模式
|
- Support dark mode
|
||||||
- 自定义主题颜色
|
- Custom theme colors
|
||||||
- 多种空间布局
|
- Various space layouts
|
||||||
- 内置 Mock 数据方案
|
- Mock data scheme
|
||||||
|
|
||||||
### 使用
|
### Usage
|
||||||
|
|
||||||
> 通过 `tdesign-starter-cli` 初始化项目仓库
|
> Initialize project with our CLI tool `tdesign-starter-cli`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
## 1、安装 tdesign-starter-cli
|
## install tdesign-starter-cli
|
||||||
npm i tdesign-starter-cli@latest -g
|
npm i tdesign-starter-cli@latest -g
|
||||||
|
|
||||||
## 2、创建项目
|
## create project
|
||||||
td-starter init
|
td-starter init
|
||||||
```
|
```
|
||||||
|
|
||||||
### 开发
|
### Develop
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
## 安装依赖
|
## install dependencies
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
## 启动项目
|
## set up
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### 构建
|
### Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
## 构建正式环境
|
## build
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
## 构建测试环境
|
## build for test
|
||||||
npm run build:test
|
npm run build:test
|
||||||
```
|
```
|
||||||
|
|
||||||
### 其他
|
|
||||||
|
|
||||||
```bash
|
### Contributing Guide
|
||||||
## 预览构建产物
|
|
||||||
npm run preview
|
|
||||||
|
|
||||||
## 代码格式检查
|
We welcome contributions to our project. Create your [Issue](https://github.com/tencent/tdesign-vue-next-starter/issues/new/choose) or Submit your [Pull Request](https://github.com/Tencent/tdesign-vue-next-starter/pulls).
|
||||||
npm run lint
|
|
||||||
|
|
||||||
## 代码格式检查与自动修复
|
|
||||||
npm run lint:fix
|
|
||||||
|
|
||||||
## style格式检查
|
|
||||||
npm run stylelint
|
|
||||||
|
|
||||||
## style格式检查与自动修复
|
|
||||||
npm run stylelint:fix
|
|
||||||
```
|
|
||||||
|
|
||||||
### 如何贡献
|
|
||||||
|
|
||||||
非常欢迎您的贡献!提交您的 [Issue](https://github.com/tencent/tdesign-vue-next-starter/issues/new/choose) 或者提交 [Pull Request](https://github.com/Tencent/tdesign-vue-next-starter/pulls)。
|
|
||||||
|
|
||||||
#### Pull Request
|
#### Pull Request
|
||||||
|
|
||||||
1. Fork 代码!
|
1. Fork it!
|
||||||
2. 创建自己的分支: `git checkout -b feat/xxxx`
|
2. Create your branch: `git checkout -b feat/xxxx`
|
||||||
3. 提交你的修改: `git commit -a 'feat(project): describe'`
|
3. Commit: `git commit -a 'feat(project): describe'`
|
||||||
4. 推送您的分支: `git push origin feat/xxxx`
|
4. Push: `git push origin feat/xxxx`
|
||||||
5. 提交 `pull request`
|
5. New Pull Request `pull request`
|
||||||
|
|
||||||
#### 贡献提交规范
|
#### Commit Specification
|
||||||
|
|
||||||
- [Angular Convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
|
- [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)
|
- [Vue Style Guide](https://v3.vuejs.org/style-guide/#rule-categories)
|
||||||
|
|
||||||
### 兼容性
|
### Compatibility
|
||||||
|
|
||||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
|
| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
|
||||||
|
|
||||||
### 开源协议
|
### License
|
||||||
|
|
||||||
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-vue-next-starter/LICENSE)。
|
|
||||||
|
|
||||||
|
The MIT License. Please see [the license file](LICENSE) for more information.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "tdesign-vue-next-starter",
|
"name": "tdesign-vue-next-starter",
|
||||||
"version": "0.4.1",
|
"version": "0.5.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:mock": "vite --open --mode mock",
|
"dev:mock": "vite --open --mode mock",
|
||||||
"dev": "vite --open --mode development",
|
"dev": "vite --open --mode development",
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.0.11",
|
"pinia": "^2.0.11",
|
||||||
|
"pinia-plugin-persistedstate": "^2.1.1",
|
||||||
"qrcode.vue": "^3.2.2",
|
"qrcode.vue": "^3.2.2",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"tdesign-icons-vue-next": "^0.1.1",
|
"tdesign-icons-vue-next": "^0.1.1",
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
<router-view :class="[mode]" />
|
<router-view :class="[mode]" />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted } from 'vue';
|
import { computed } from 'vue';
|
||||||
import config from '@/config/style';
|
|
||||||
import { useSettingStore } from '@/store';
|
import { useSettingStore } from '@/store';
|
||||||
|
|
||||||
const store = useSettingStore();
|
const store = useSettingStore();
|
||||||
|
@ -11,10 +10,6 @@ const store = useSettingStore();
|
||||||
const mode = computed(() => {
|
const mode = computed(() => {
|
||||||
return store.displayMode;
|
return store.displayMode;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
store.updateConfig({ ...config });
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import '@/style/variables.less';
|
@import '@/style/variables.less';
|
||||||
|
|
|
@ -34,6 +34,6 @@ const crumbs = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.tdesign-breadcrumb {
|
.tdesign-breadcrumb {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
import { computed, ComputedRef } from 'vue';
|
import { computed, ComputedRef } from 'vue';
|
||||||
import { useTabsRouterStore } from '@/store';
|
import { useTabsRouterStore } from '@/store';
|
||||||
|
|
||||||
|
// <suspense>标签属于实验性功能,请谨慎使用
|
||||||
// 如果存在需解决/page/1=> /page/2 刷新数据问题 请修改代码 使用activeRouteFullPath 作为key
|
// 如果存在需解决/page/1=> /page/2 刷新数据问题 请修改代码 使用activeRouteFullPath 作为key
|
||||||
// <component :is="Component" :key="activeRouteFullPath" />
|
// <suspense>
|
||||||
|
// <component :is="Component" :key="activeRouteFullPath" />
|
||||||
|
// </suspense>
|
||||||
|
|
||||||
// import { useRouter } from 'vue-router';
|
// import { useRouter } from 'vue-router';
|
||||||
// const activeRouteFullPath = computed(() => {
|
// const activeRouteFullPath = computed(() => {
|
||||||
|
|
|
@ -19,19 +19,23 @@
|
||||||
<t-dropdown
|
<t-dropdown
|
||||||
trigger="context-menu"
|
trigger="context-menu"
|
||||||
:min-column-width="128"
|
:min-column-width="128"
|
||||||
:popup-props="{ overlayClassName: 'route-tabs-dropdown' }"
|
:popup-props="{
|
||||||
|
overlayClassName: 'route-tabs-dropdown',
|
||||||
|
onVisibleChange: (visible: boolean, ctx) => handleTabMenuClick(visible, ctx, routeItem.path),
|
||||||
|
visible: activeTabPath === routeItem.path,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template v-if="!routeItem.isHome">
|
<template v-if="!routeItem.isHome">
|
||||||
{{ routeItem.title }}
|
{{ routeItem.title }}
|
||||||
</template>
|
</template>
|
||||||
<t-icon v-else name="home" />
|
<t-icon v-else name="home" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<t-dropdown-menu v-if="$route.path === routeItem.path">
|
<t-dropdown-menu>
|
||||||
<t-dropdown-item @click="() => handleRefresh(routeItem, index)">
|
<t-dropdown-item @click="() => handleRefresh(routeItem, index)">
|
||||||
<t-icon name="refresh" />
|
<t-icon name="refresh" />
|
||||||
刷新
|
刷新
|
||||||
</t-dropdown-item>
|
</t-dropdown-item>
|
||||||
<t-dropdown-item v-if="index > 0" @click="() => handleCloseAhead(routeItem.path, index)">
|
<t-dropdown-item v-if="index > 1" @click="() => handleCloseAhead(routeItem.path, index)">
|
||||||
<t-icon name="arrow-left" />
|
<t-icon name="arrow-left" />
|
||||||
关闭左侧
|
关闭左侧
|
||||||
</t-dropdown-item>
|
</t-dropdown-item>
|
||||||
|
@ -42,7 +46,7 @@
|
||||||
<t-icon name="arrow-right" />
|
<t-icon name="arrow-right" />
|
||||||
关闭右侧
|
关闭右侧
|
||||||
</t-dropdown-item>
|
</t-dropdown-item>
|
||||||
<t-dropdown-item @click="() => handleCloseOther(routeItem.path, index)">
|
<t-dropdown-item v-if="tabRouters.length > 2" @click="() => handleCloseOther(routeItem.path, index)">
|
||||||
<t-icon name="close-circle" />
|
<t-icon name="close-circle" />
|
||||||
关闭其它
|
关闭其它
|
||||||
</t-dropdown-item>
|
</t-dropdown-item>
|
||||||
|
@ -63,7 +67,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { nextTick, computed } from 'vue';
|
import { nextTick, ref, computed } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useSettingStore, useTabsRouterStore } from '@/store';
|
import { useSettingStore, useTabsRouterStore } from '@/store';
|
||||||
import { prefix } from '@/config/global';
|
import { prefix } from '@/config/global';
|
||||||
|
@ -79,6 +83,7 @@ const router = useRouter();
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
const tabsRouterStore = useTabsRouterStore();
|
const tabsRouterStore = useTabsRouterStore();
|
||||||
const tabRouters = computed(() => tabsRouterStore.tabRouters.filter((route) => route.isAlive || route.isHome));
|
const tabRouters = computed(() => tabsRouterStore.tabRouters.filter((route) => route.isAlive || route.isHome));
|
||||||
|
const activeTabPath = ref('');
|
||||||
|
|
||||||
const handleChangeCurrentTab = (path: string) => {
|
const handleChangeCurrentTab = (path: string) => {
|
||||||
const { tabRouters } = tabsRouterStore;
|
const { tabRouters } = tabsRouterStore;
|
||||||
|
@ -100,14 +105,46 @@ const handleRefresh = (route: TRouterInfo, routeIdx: number) => {
|
||||||
tabsRouterStore.toggleTabRouterAlive(routeIdx);
|
tabsRouterStore.toggleTabRouterAlive(routeIdx);
|
||||||
router.replace({ path: route.path, query: route.query });
|
router.replace({ path: route.path, query: route.query });
|
||||||
});
|
});
|
||||||
|
activeTabPath.value = null;
|
||||||
};
|
};
|
||||||
const handleCloseAhead = (path: string, routeIdx: number) => {
|
const handleCloseAhead = (path: string, routeIdx: number) => {
|
||||||
tabsRouterStore.subtractTabRouterAhead({ path, routeIdx });
|
tabsRouterStore.subtractTabRouterAhead({ path, routeIdx });
|
||||||
|
|
||||||
|
handleOperationEffect('ahead', routeIdx);
|
||||||
};
|
};
|
||||||
const handleCloseBehind = (path: string, routeIdx: number) => {
|
const handleCloseBehind = (path: string, routeIdx: number) => {
|
||||||
tabsRouterStore.subtractTabRouterBehind({ path, routeIdx });
|
tabsRouterStore.subtractTabRouterBehind({ path, routeIdx });
|
||||||
|
|
||||||
|
handleOperationEffect('behind', routeIdx);
|
||||||
};
|
};
|
||||||
const handleCloseOther = (path: string, routeIdx: number) => {
|
const handleCloseOther = (path: string, routeIdx: number) => {
|
||||||
tabsRouterStore.subtractTabRouterOther({ path, routeIdx });
|
tabsRouterStore.subtractTabRouterOther({ path, routeIdx });
|
||||||
|
|
||||||
|
handleOperationEffect('other', routeIdx);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理非当前路由操作的副作用
|
||||||
|
const handleOperationEffect = (type: 'other' | 'ahead' | 'behind', routeIndex: number) => {
|
||||||
|
const currentPath = router.currentRoute.value.path;
|
||||||
|
const { tabRouters } = tabsRouterStore;
|
||||||
|
|
||||||
|
const currentIdx = tabRouters.findIndex((i) => i.path === currentPath);
|
||||||
|
// 存在三种情况需要刷新当前路由
|
||||||
|
// 点击非当前路由的关闭其他、点击非当前路由的关闭左侧且当前路由小于触发路由、点击非当前路由的关闭右侧且当前路由大于触发路由
|
||||||
|
const needRefreshRouter =
|
||||||
|
(type === 'other' && currentIdx !== routeIndex) ||
|
||||||
|
(type === 'ahead' && currentIdx < routeIndex) ||
|
||||||
|
(type === 'behind' && currentIdx === -1);
|
||||||
|
if (needRefreshRouter) {
|
||||||
|
const nextRouteIdx = type === 'behind' ? tabRouters.length - 1 : 1;
|
||||||
|
const nextRouter = tabRouters[nextRouteIdx];
|
||||||
|
router.push({ path: nextRouter.path, query: nextRouter.query });
|
||||||
|
}
|
||||||
|
|
||||||
|
activeTabPath.value = null;
|
||||||
|
};
|
||||||
|
const handleTabMenuClick = (visible: boolean, ctx, path: string) => {
|
||||||
|
if (ctx.trigger === 'document') activeTabPath.value = null;
|
||||||
|
if (visible) activeTabPath.value = path;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</template>
|
</template>
|
||||||
<menu-content :nav-data="menu" />
|
<menu-content :nav-data="menu" />
|
||||||
<template #operations>
|
<template #operations>
|
||||||
<span class="version-container"> {{ !collapsed && 'TDesign Starter' }} {{ pgk.version }} </span>
|
<span class="version-container"> {{ !collapsed ? 'TDesign Starter' : '' }} {{ pgk.version }} </span>
|
||||||
</template>
|
</template>
|
||||||
</t-menu>
|
</t-menu>
|
||||||
<div :class="`${prefix}-side-nav-placeholder${collapsed ? '-hidden' : ''}`"></div>
|
<div :class="`${prefix}-side-nav-placeholder${collapsed ? '-hidden' : ''}`"></div>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, watch, onBeforeUnmount } from 'vue';
|
import { computed, onMounted, watch } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useSettingStore, useTabsRouterStore } from '@/store';
|
import { useSettingStore, useTabsRouterStore } from '@/store';
|
||||||
|
@ -59,28 +59,10 @@ const appendNewRoute = () => {
|
||||||
tabsRouterStore.appendTabRouterList({ path, query, title: title as string, name, isAlive: true });
|
tabsRouterStore.appendTabRouterList({ path, query, title: title as string, name, isAlive: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTabRouterListCache = () => {
|
|
||||||
tabsRouterStore.initTabRouterList(JSON.parse(localStorage.getItem('tabRouterList')));
|
|
||||||
};
|
|
||||||
const setTabRouterListCache = () => {
|
|
||||||
const { tabRouters } = tabsRouterStore;
|
|
||||||
localStorage.setItem('tabRouterList', JSON.stringify(tabRouters));
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
appendNewRoute();
|
appendNewRoute();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果不需要持久化标签页可以注释掉以下的 onMounted 和 onBeforeUnmount 的内容
|
|
||||||
onMounted(() => {
|
|
||||||
if (localStorage.getItem('tabRouterList')) getTabRouterListCache();
|
|
||||||
window.addEventListener('beforeunload', setTabRouterListCache);
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
window.removeEventListener('beforeunload', setTabRouterListCache);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.path,
|
() => route.path,
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -124,8 +124,18 @@ const MODE_OPTIONS = [
|
||||||
{ type: 'dark', text: '暗黑' },
|
{ type: 'dark', text: '暗黑' },
|
||||||
{ type: 'auto', text: '跟随系统' },
|
{ type: 'auto', text: '跟随系统' },
|
||||||
];
|
];
|
||||||
|
const initStyleConfig = () => {
|
||||||
|
const styleConfig = STYLE_CONFIG;
|
||||||
|
for (const key in styleConfig) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(styleConfig, key)) {
|
||||||
|
styleConfig[key] = settingStore[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const formData = ref({ ...STYLE_CONFIG });
|
return styleConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formData = ref({ ...initStyleConfig() });
|
||||||
const isColoPickerDisplay = ref(false);
|
const isColoPickerDisplay = ref(false);
|
||||||
|
|
||||||
const showSettingPanel = computed({
|
const showSettingPanel = computed({
|
||||||
|
|
|
@ -25,7 +25,7 @@ import OutputOverview from './components/OutputOverview.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.row-container {
|
.row-container:not(:last-child) {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -38,14 +38,14 @@ import Thumbnail from '@/components/thumbnail/index.vue';
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
color: var(--td-text-color-secondary);
|
color: var(--td-text-color-secondary);
|
||||||
|
height: calc(75vh - 254px);
|
||||||
|
min-height: 156px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recommend-container {
|
.recommend-container {
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
top: 175px;
|
|
||||||
padding: 24px 48px;
|
padding: 24px 48px;
|
||||||
width: 640px;
|
width: 640px;
|
||||||
background: var(--td-bg-color-container);
|
background: var(--td-bg-color-container);
|
||||||
|
|
|
@ -5,16 +5,15 @@ import 'nprogress/nprogress.css'; // progress bar style
|
||||||
import { getPermissionStore, getUserStore } from '@/store';
|
import { getPermissionStore, getUserStore } from '@/store';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
|
|
||||||
const permissionStore = getPermissionStore();
|
|
||||||
const userStore = getUserStore();
|
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false });
|
NProgress.configure({ showSpinner: false });
|
||||||
|
|
||||||
const { whiteListRouters } = permissionStore;
|
|
||||||
|
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
|
|
||||||
|
const userStore = getUserStore();
|
||||||
|
const permissionStore = getPermissionStore();
|
||||||
|
const { whiteListRouters } = permissionStore;
|
||||||
|
|
||||||
const { token } = userStore;
|
const { token } = userStore;
|
||||||
if (token) {
|
if (token) {
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
|
@ -58,6 +57,9 @@ router.beforeEach(async (to, from, next) => {
|
||||||
|
|
||||||
router.afterEach((to) => {
|
router.afterEach((to) => {
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
|
const userStore = getUserStore();
|
||||||
|
const permissionStore = getPermissionStore();
|
||||||
|
|
||||||
userStore.logout();
|
userStore.logout();
|
||||||
permissionStore.restore();
|
permissionStore.restore();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
|
import { createPersistedState } from 'pinia-plugin-persistedstate';
|
||||||
|
|
||||||
const store = createPinia();
|
const store = createPinia();
|
||||||
|
store.use(createPersistedState());
|
||||||
|
|
||||||
export { store };
|
export { store };
|
||||||
|
|
||||||
|
|
|
@ -73,4 +73,5 @@ export const useNotificationStore = defineStore('notification', {
|
||||||
this.msgData = data;
|
this.msgData = data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
import keys from 'lodash/keys';
|
||||||
import { COLOR_TOKEN, LIGHT_CHART_COLORS, DARK_CHART_COLORS, TColorSeries } from '@/config/color';
|
import { COLOR_TOKEN, LIGHT_CHART_COLORS, DARK_CHART_COLORS, TColorSeries } from '@/config/color';
|
||||||
import STYLE_CONFIG from '@/config/style';
|
import STYLE_CONFIG from '@/config/style';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
|
@ -67,6 +68,9 @@ export const useSettingStore = defineStore('setting', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: {
|
||||||
|
paths: [...keys(STYLE_CONFIG), 'colorList', 'chartColors'],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getSettingStore() {
|
export function getSettingStore() {
|
||||||
|
|
|
@ -68,6 +68,7 @@ export const useTabsRouterStore = defineStore('tabsRouter', {
|
||||||
newRoutes?.forEach((route: TRouterInfo) => this.appendTabRouterList(route));
|
newRoutes?.forEach((route: TRouterInfo) => this.appendTabRouterList(route));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getTabsRouterStore() {
|
export function getTabsRouterStore() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { TOKEN_NAME } from '@/config/global';
|
import { TOKEN_NAME } from '@/config/global';
|
||||||
import { store } from '@/store';
|
import { store, usePermissionStore } from '@/store';
|
||||||
|
|
||||||
const InitUserInfo = {
|
const InitUserInfo = {
|
||||||
roles: [],
|
roles: [],
|
||||||
|
@ -79,6 +79,12 @@ export const useUserStore = defineStore('user', {
|
||||||
this.token = '';
|
this.token = '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
persist: {
|
||||||
|
afterRestore: (ctx) => {
|
||||||
|
const permissionStore = usePermissionStore();
|
||||||
|
permissionStore.initRoutes(ctx.store.roles);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function getUserStore() {
|
export function getUserStore() {
|
||||||
|
|
|
@ -108,7 +108,7 @@
|
||||||
|
|
||||||
&-footer-layout {
|
&-footer-layout {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-bottom: @spacer-2;
|
margin-bottom: @spacer-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// slideBar
|
// slideBar
|
||||||
|
|
Loading…
Reference in New Issue
Block a user