Merge branch 'develop' of github.com:Tencent/tdesign-vue-next-starter into main

This commit is contained in:
Uyarn 2022-10-13 19:04:41 +08:00
commit c9f12bd478
49 changed files with 265 additions and 161 deletions

120
README-zh_CN.md Normal file
View 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)。

View File

@ -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.

View File

@ -1,6 +1,6 @@
{ {
"name": "tdesign-vue-next-starter", "name": "tdesign-vue-next-starter",
"version": "0.4.1", "version": "0.5.2",
"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,10 +24,11 @@
"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",
"tdesign-vue-next": "0.20.3", "tdesign-vue-next": "^0.24.2-alpha.2",
"tvision-color": "^1.3.1", "tvision-color": "^1.3.1",
"vue": "^3.2.31", "vue": "^3.2.31",
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
@ -64,7 +65,7 @@
"stylelint-config-prettier": "~9.0.3", "stylelint-config-prettier": "~9.0.3",
"stylelint-less": "1.0.1", "stylelint-less": "1.0.1",
"stylelint-order": "~4.1.0", "stylelint-order": "~4.1.0",
"typescript": "~4.7.4", "typescript": "~4.8.4",
"vite": "^2.7.1", "vite": "^2.7.1",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",
"vite-svg-loader": "^3.1.0", "vite-svg-loader": "^3.1.0",

View File

@ -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,14 +10,8 @@ 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';
#nprogress .bar { #nprogress .bar {
background: var(--td-brand-color) !important; background: var(--td-brand-color) !important;
} }

View File

@ -94,8 +94,6 @@ const handleClickDelete = (product: CardProductType) => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.list-card-item { .list-card-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -44,8 +44,6 @@ const dynamicComponent = computed(() => {
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.result { .result {
&-link { &-link {
color: var(--td-brand-color); color: var(--td-brand-color);

View File

@ -48,7 +48,6 @@ const iconCls = computed(() => ['trend-icon-container']);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.trend { .trend {
&-container { &-container {
&__up { &__up {

View File

@ -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>

View File

@ -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(() => {
@ -35,8 +38,6 @@ const isRefreshing = computed(() => {
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.fade-leave-active, .fade-leave-active,
.fade-enter-active { .fade-enter-active {
transition: opacity @anim-duration-slow @anim-time-fn-easing; transition: opacity @anim-duration-slow @anim-time-fn-easing;

View File

@ -7,8 +7,6 @@ import { prefix } from '@/config/global';
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.@{starter-prefix}-footer { .@{starter-prefix}-footer {
color: var(--td-text-color-placeholder); color: var(--td-text-color-placeholder);
line-height: 20px; line-height: 20px;

View File

@ -155,7 +155,6 @@ const navToHelper = () => {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.@{starter-prefix}-header { .@{starter-prefix}-header {
&-layout { &-layout {
height: 64px; height: 64px;

View File

@ -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>

View File

@ -5,7 +5,7 @@
:layout="settingStore.layout" :layout="settingStore.layout"
:is-fixed="settingStore.isSidebarFixed" :is-fixed="settingStore.isSidebarFixed"
:menu="sideMenu" :menu="sideMenu"
:theme="settingStore.mode" :theme="settingStore.displayMode"
:is-compact="settingStore.isSidebarCompact" :is-compact="settingStore.isSidebarCompact"
/> />
</template> </template>

View File

@ -57,7 +57,7 @@ const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
}); });
return list return list
.map((item) => { .map((item) => {
const path = basePath ? `${basePath}/${item.path}` : item.path; const path = basePath && !item.path.includes(basePath) ? `${basePath}/${item.path}` : item.path;
return { return {
path, path,
title: item.meta?.title, title: item.meta?.title,

View File

@ -77,8 +77,6 @@ const goDetail = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.header-msg { .header-msg {
width: 400px; width: 400px;
height: 500px; height: 500px;

View File

@ -53,8 +53,6 @@ const changeSearchFocus = (value: boolean) => {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.header-menu-search { .header-menu-search {
display: flex; display: flex;
margin-left: 16px; margin-left: 16px;

View File

@ -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>

View File

@ -12,7 +12,7 @@
<template v-else> <template v-else>
<t-layout key="no-side"> <t-layout key="no-side">
<t-header /> <t-header><layout-header /> </t-header>
<t-layout :class="mainLayoutCls"> <t-layout :class="mainLayoutCls">
<layout-side-nav /> <layout-side-nav />
<layout-content /> <layout-content />
@ -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,
() => { () => {

View File

@ -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({
@ -202,8 +212,6 @@ watchEffect(() => {
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.tdesign-setting { .tdesign-setting {
z-index: 100; z-index: 100;
position: fixed; position: fixed;

View File

@ -155,8 +155,6 @@ const onStokeDataChange = (checkedValues: string[]) => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.dashboard-overview-card { .dashboard-overview-card {
:deep(.t-card__header) { :deep(.t-card__header) {
padding-bottom: 24px; padding-bottom: 24px;

View File

@ -66,8 +66,6 @@ const getRankClass = (index: number) => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.dashboard-rank-card { .dashboard-rank-card {
padding: 8px; padding: 8px;

View File

@ -153,8 +153,6 @@ watch(
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.dashboard-item { .dashboard-item {
padding: 8px; padding: 8px;

View File

@ -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>

View File

@ -163,8 +163,6 @@ const onMaterialChange = (value: string[]) => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.row-margin { .row-margin {
margin-top: 16px; margin-top: 16px;
} }

View File

@ -54,7 +54,6 @@ export default defineComponent({
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.operator-gap { .operator-gap {
margin-left: 20px; margin-left: 20px;
} }

View File

@ -1,5 +1,3 @@
@import '@/style/variables.less';
.detail-base { .detail-base {
:deep(.t-card) { :deep(.t-card) {
padding: 8px; padding: 8px;

View File

@ -1,5 +1,3 @@
@import '@/style/variables.less';
.secondary-notification { .secondary-notification {
background-color: var(--td-bg-color-container); background-color: var(--td-bg-color-container);
border-radius: @border-radius; border-radius: @border-radius;

View File

@ -1,5 +1,3 @@
@import '@/style/variables.less';
.form-basic-container { .form-basic-container {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,5 +1,3 @@
@import '@/style/variables';
.form-step-container { .form-step-container {
background-color: var(--td-bg-color-container); background-color: var(--td-bg-color-container);

View File

@ -187,8 +187,6 @@ const getContainer = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables';
.payment-col { .payment-col {
display: flex; display: flex;

View File

@ -146,8 +146,6 @@ const handleManageProduct = (product) => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.list-card { .list-card {
height: 100%; height: 100%;

View File

@ -271,7 +271,6 @@ const getContainer = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.list-common-table { .list-common-table {
background-color: var(--td-bg-color-container); background-color: var(--td-bg-color-container);
padding: 30px 32px; padding: 30px 32px;

View File

@ -43,7 +43,6 @@ const onInput = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.table-tree-container { .table-tree-container {
background-color: var(--td-bg-color-container); background-color: var(--td-bg-color-container);
border-radius: @border-radius; border-radius: @border-radius;

View File

@ -36,7 +36,6 @@ const navToHelper = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.login-header { .login-header {
height: 64px; height: 64px;
padding: 0 24px; padding: 0 24px;

View File

@ -1,5 +1,3 @@
@import '@/style/variables.less';
.light { .light {
&.login-wrapper { &.login-wrapper {
background-color: white; background-color: white;

View File

@ -29,8 +29,6 @@ import Thumbnail from '@/components/thumbnail/index.vue';
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.result-slot-container { .result-slot-container {
position: relative; position: relative;
display: flex; display: flex;
@ -38,14 +36,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);

View File

@ -15,8 +15,6 @@ export default {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.result-success { .result-success {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -15,8 +15,6 @@ export default {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less';
.result-success { .result-success {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,5 +1,3 @@
@import '@/style/variables';
:deep(.t-card__title) { :deep(.t-card__title) {
font-size: 20px; font-size: 20px;
font-weight: 500; font-weight: 500;

View File

@ -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();
} }

View File

@ -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 };

View File

@ -73,4 +73,5 @@ export const useNotificationStore = defineStore('notification', {
this.msgData = data; this.msgData = data;
}, },
}, },
persist: true,
}); });

View File

@ -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() {

View File

@ -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() {

View File

@ -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,14 @@ export const useUserStore = defineStore('user', {
this.token = ''; this.token = '';
}, },
}, },
persist: {
afterRestore: (ctx) => {
if (ctx.store.roles && ctx.store.roles.length > 0) {
const permissionStore = usePermissionStore();
permissionStore.initRoutes(ctx.store.roles);
}
},
},
}); });
export function getUserStore() { export function getUserStore() {

View File

@ -1,4 +1,3 @@
@import './variables.less';
@import './font-family.less'; @import './font-family.less';
@import './theme/index.less'; @import './theme/index.less';
@import './reset.less'; @import './reset.less';

View File

@ -1,4 +1,3 @@
@import './variables.less';
@import './font-family.less'; @import './font-family.less';
// layout rewrite // layout rewrite
@ -108,7 +107,7 @@
&-footer-layout { &-footer-layout {
padding: 0; padding: 0;
margin-bottom: @spacer-2; margin-bottom: @spacer-3;
} }
// slideBar // slideBar

View File

@ -57,7 +57,7 @@ const transform: AxiosTransform = {
const { apiUrl, isJoinPrefix, urlPrefix, joinParamsToUrl, formatDate, joinTime = true } = options; const { apiUrl, isJoinPrefix, urlPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
// 添加接口前缀 // 添加接口前缀
if (isJoinPrefix) { if (isJoinPrefix && urlPrefix && isString(urlPrefix)) {
config.url = `${urlPrefix}${config.url}`; config.url = `${urlPrefix}${config.url}`;
} }

View File

@ -19,6 +19,18 @@ export default ({ mode }: ConfigEnv): UserConfig => {
}, },
}, },
css: {
preprocessorOptions: {
less: {
modifyVars: {
hack: `true; @import (reference) "${path.resolve('src/style/variables.less')}";`,
},
math: 'strict',
javascriptEnabled: true,
},
},
},
plugins: [ plugins: [
createVuePlugin(), createVuePlugin(),
vueJsx(), vueJsx(),