mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-05-22 04:39:32 +08:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
f60a107997
1
.github/workflows/docs-deploy.yaml
vendored
1
.github/workflows/docs-deploy.yaml
vendored
@ -9,7 +9,6 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build-and-deploy:
|
||||||
if: github.event.pull_request.merged == true
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
69
CHANGELOG.md
69
CHANGELOG.md
@ -1,5 +1,74 @@
|
|||||||
# CHANGE LOG
|
# CHANGE LOG
|
||||||
|
|
||||||
|
## 4.5.0
|
||||||
|
|
||||||
|
破坏性更新。
|
||||||
|
|
||||||
|
更新 `vue` 版本至 `3.4.0`,请查看相关变更:[Vue 3.4.0](https://github.com/vuejs/core/blob/main/CHANGELOG.md)。该版本破坏性更新了一些东西,例如:
|
||||||
|
|
||||||
|
- `JSX` 命名空间默认移除
|
||||||
|
- `ReactiveTransform` 移除
|
||||||
|
- `v-is` 指令移除
|
||||||
|
|
||||||
|
更新 `@vitejs/plugin-vue` 版本至 `5.0.0`,请查看相关变更:[vite-plugin-vue](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)。该版本破坏性更新了一些东西,例如:
|
||||||
|
|
||||||
|
- 放弃 `ReactivityTransform` 支持
|
||||||
|
- 放弃 `node14, 16` 版本支持
|
||||||
|
- 放弃 `vite4.x` 版本支持
|
||||||
|
- 弃用 `defineModel` 配置,`vue3.4.0` 版本该功能已经稳定
|
||||||
|
|
||||||
|
解决 `sameLevel` 问题与核心包 `store/men` 的一些问题。提高了性能,避免了潜在的空引用问题。
|
||||||
|
|
||||||
|
是统一 `types` 包的导入导出行为。
|
||||||
|
|
||||||
|
## Feats
|
||||||
|
|
||||||
|
- 统一 `types` 包下的导出方式,现在统一为 `import type { xxx } from '@/types'` 导入
|
||||||
|
- `RQRCode` 组件
|
||||||
|
- 在 `loading` 状态下会模糊显示二维码,并且展示 `loading` 状态
|
||||||
|
- 优化显示 `error` 状态下默认按钮样式
|
||||||
|
- 更新 `README.md`, `README-ZH.md` 文档
|
||||||
|
- 取消 `changeModelValue` 节流锁
|
||||||
|
- 优化 `changeModelValue`, `updateMenuKeyWhenRouteUpdate` 方法,避免潜在的空引用问题
|
||||||
|
- 插件相关
|
||||||
|
- 更新 `vue` 版本至 `3.4.0`
|
||||||
|
- 更新 `@vitejs/plugin-vue-jsx` 版本至 `3.1.0`
|
||||||
|
- `RModal` 组件相关
|
||||||
|
- 新增 `memo` 配置项,用于配置是否记忆上一次的位置
|
||||||
|
- `RChart` 组件
|
||||||
|
- 补充部分注释
|
||||||
|
- 新增 `isDispose` 方法,检测当前图表是否被卸载
|
||||||
|
- 新增 `AppVersionProvider` 注入器,用于注入 `appVersion` 全局变量,检测是否需要重新加载页面
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- 修复初始化的时候面包屑为空的问题
|
||||||
|
- 修复 `sameLevel` 平级模式面包屑追加问题
|
||||||
|
- `RModal` 组件
|
||||||
|
- 修复初始化配置 `show = true` 时,`dad` 属性不生效的问题
|
||||||
|
|
||||||
|
## 4.4.7
|
||||||
|
|
||||||
|
## Feats
|
||||||
|
|
||||||
|
- 更新 `vue` 版本至 `3.3.13` 版本
|
||||||
|
- 更新 `naive-ui` 版本至 `3.36.0`。新增了几个新组件
|
||||||
|
- 更新 `vite` 版本至 `5.0.10`
|
||||||
|
- `appConfig` 相关
|
||||||
|
- 移除 `APP_WATERMARK_CONFIG` 配置项,现在水印配置项会被 `watermarkConfig` 替代
|
||||||
|
- 移除 `ROOT_ROUTE` 配置项,现在根路由配置项会被 `appRootRoute` 替代
|
||||||
|
- `variable` 相关
|
||||||
|
- 移除 `variable` 管理 `ROO_ROUTE` 配置项
|
||||||
|
- `commit-message` 新增 `plugin` 更新相关前缀配置
|
||||||
|
- `RQRCode` 组件
|
||||||
|
- 调整 `loading` 透明度
|
||||||
|
- `downloadQRCode` 方法将会返回一个 `Promise` 对象
|
||||||
|
- `basic` 包
|
||||||
|
- `downloadAnyFile` 方法将会返回一个 `Promise` 对象
|
||||||
|
- `types` 包
|
||||||
|
- 新增 `ReturnPromiseType` 工具类型,用于获取函数返回值的 `Promise` 类型
|
||||||
|
- 新增 `ConditionalExclude` 工具类型,用于条件排除指定类型
|
||||||
|
|
||||||
## 4.4.6
|
## 4.4.6
|
||||||
|
|
||||||
## Feats
|
## Feats
|
||||||
|
67
README-ZH.md
67
README-ZH.md
@ -1,6 +1,22 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/XiaoDaiGua-Ray/ray-template"> <img alt="Ray Template" width="200" height="200" src="https://r2chevereto.yka.moe/longmao.navigator.th.png"> </a> <br> <br>
|
<a href="https://github.com/XiaoDaiGua-Ray/ray-template">
|
||||||
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/LICENSE"><img src="https://img.shields.io/github/license/XiaoDaiGua-Ray/ray-template" alt="LICENSE"></a>
|
<img
|
||||||
|
alt="Ray Template"
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
src="https://r2chevereto.yka.moe/longmao.navigator.th.png"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="https://nodejs.org/en/about/previous-releases"><img src="https://img.shields.io/node/v/vite.svg" alt="node compatibility"></a>
|
||||||
|
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/LICENSE"
|
||||||
|
><img
|
||||||
|
src="https://img.shields.io/github/license/XiaoDaiGua-Ray/ray-template"
|
||||||
|
alt="LICENSE"
|
||||||
|
/></a>
|
||||||
|
<a href="#badge"><img src="https://img.shields.io/github/languages/top/XiaoDaiGua-Ray/ray-template" alt="language"></a>
|
||||||
|
<a href="https://www.npmjs.com/package/ray-template"><img src="https://img.shields.io/npm/v/ray-template" alt="npm package"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
@ -9,32 +25,40 @@
|
|||||||
|
|
||||||
简体中文 | [English](https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/README.md)
|
简体中文 | [English](https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/README.md)
|
||||||
|
|
||||||
一个 `免费`、`高效`、`特性完整` 并且基于 vite5.x & ts(x) & pinia & vue3.x 等最新技术的中后台模板。
|
一个 `完全免费`、`高效`、`特性完整` 并且基于 vite5.x & ts(x) & pinia & vue3.x 等最新技术的中后台模板。
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## 🌻 简介
|
||||||
|
|
||||||
|
`Ray Template`采用前沿前端技术,摒弃繁杂与臃肿,采用模块化设计,解耦数据、方法和视图,专注业务开发。提供丰富配置和丰富的模板 `Hooks`,支持个性化定制,满足你的项目需求。
|
||||||
|
|
||||||
## ✨ 特性
|
## ✨ 特性
|
||||||
|
|
||||||
- **靠爱发电**:几乎包含市面常见的模板特性并且全部免费使用
|
- `全新技术栈:`使用 ts(x), vite5.x, vue3.x, pinia 等前端前沿技术开发
|
||||||
- **最新技术栈**:使用 vue3.x/vite5.x/pinia 等前端前沿技术开发
|
- `主题:`可配置的主题
|
||||||
- **TypeScript**:应用程序级 JavaScript 的语言
|
- `国际化:`内置完善的国际化方案
|
||||||
- **主题**:可配置的主题
|
- `权限:`内置完善的动态路由权限生成方案
|
||||||
- **国际化**:内置完善的国际化方案
|
- `组件:`二次封装了多个常用的组件
|
||||||
- **Mock 数据**:内置 Mock 数据方案
|
- `工具包:`常用的工具函数封装
|
||||||
- **权限**:内置完善的动态路由权限生成方案
|
- `缓存:`任意深度页面缓存
|
||||||
- **组件**:二次封装了多个常用的组件
|
- `模块化设计:`解耦管理的数据、方法、视图,放心二次开发
|
||||||
- **Axios 请求**:二次封装 axios 库,支持:取消、防抖、自动重复取消等功能
|
- `配置化:`支持丰富的配置项
|
||||||
- **缓存**:任意深度页面缓存
|
- `代码风格:`内置 prettier, eslint 等代码风格工具
|
||||||
- **SVG**:内置 svg icon 解决方案
|
- `多端适配:`支持 pc, phone, pad
|
||||||
- **独立的 Data Methods Views**:解耦管理的数据、方法、视图,放心二次开发
|
- `文档:`完善的文档
|
||||||
- **模板专属 hooks**:基于模板特性封装的 hooks 让你更加方便的使用模板一些功能
|
- `Mock 数据:`内置 Mock 数据方案
|
||||||
|
- `Axios 请求:`二次封装 axios 库,支持:取消、防抖、自动重复取消等功能
|
||||||
|
- `SVG:`内置 svg icon 解决方案
|
||||||
|
- `Hooks:`基于模板特性封装的 hooks 让你更加方便的使用模板一些功能
|
||||||
|
- `TypeScript:`提供完整的类型
|
||||||
|
|
||||||
## 🪄 预览地址
|
## 👀 预览地址
|
||||||
|
|
||||||
- [点击预览](https://xiaodaigua-ray.github.io/ray-template/#/)
|
- [点击预览](https://xiaodaigua-ray.github.io/ray-template/#/)
|
||||||
- [点击预览(加速地址)](https://ray-template.yunkuangao.com/#/)
|
- [点击预览(加速地址)](https://ray-template.yunkuangao.com/#/)
|
||||||
|
|
||||||
## 🦾 文档地址
|
## 📌 文档地址
|
||||||
|
|
||||||
- [文档](https://xiaodaigua-ray.github.io/ray-template-doc/)
|
- [文档](https://xiaodaigua-ray.github.io/ray-template-doc/)
|
||||||
- [文档(加速地址)](https://ray-template.yunkuangao.com/ray-template-doc/)
|
- [文档(加速地址)](https://ray-template.yunkuangao.com/ray-template-doc/)
|
||||||
@ -50,8 +74,9 @@
|
|||||||
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
|
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
|
||||||
- [TypeScript](https://www.typescriptlang.org/) - 熟悉 TypeScript 基本语法
|
- [TypeScript](https://www.typescriptlang.org/) - 熟悉 TypeScript 基本语法
|
||||||
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
|
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
|
||||||
|
- [Vue-Hooks-Plus] - 熟悉 vue-hooks-plus useRequest 方法的基本使用
|
||||||
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router4.x 基本使用
|
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router4.x 基本使用
|
||||||
- [Naive-UI](https://www.naiveui.com) - ui 基本使用
|
- [Naive-UI](https://www.naiveui.com) - naive ui 基本使用
|
||||||
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
|
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
|
||||||
- [Pinia](https://pinia.vuejs.org/zh/introduction.html) - 状态管理器 pinia 使用
|
- [Pinia](https://pinia.vuejs.org/zh/introduction.html) - 状态管理器 pinia 使用
|
||||||
- [TSX](https://github.com/vuejs/babel-plugin-jsx/blob/main/packages/babel-plugin-jsx/README-zh_CN.md) - tsx 基本语法
|
- [TSX](https://github.com/vuejs/babel-plugin-jsx/blob/main/packages/babel-plugin-jsx/README-zh_CN.md) - tsx 基本语法
|
||||||
@ -98,9 +123,9 @@ pnpm preview
|
|||||||
pnpm report
|
pnpm report
|
||||||
```
|
```
|
||||||
|
|
||||||
### 开发
|
### 快速开发
|
||||||
|
|
||||||
简介、易上手是该模板的核心思路。所以你可以放心的直接删除 `views/demo` `router/moduels/demo` 下的所有文件,这样就是一个干净的项目了。
|
只需要删除 `views/demo`, `router/modules/demo` 下的文件即可得到一个干净的项目模板。
|
||||||
|
|
||||||
## 🪴 项目活动
|
## 🪴 项目活动
|
||||||
|
|
||||||
|
103
README.md
103
README.md
@ -1,6 +1,22 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/XiaoDaiGua-Ray/ray-template"> <img alt="Ray Template" width="200" height="200" src="https://r2chevereto.yka.moe/longmao.navigator.th.png"> </a> <br> <br>
|
<a href="https://github.com/XiaoDaiGua-Ray/ray-template">
|
||||||
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/LICENSE"><img src="https://img.shields.io/github/license/XiaoDaiGua-Ray/ray-template" alt="LICENSE"></a>
|
<img
|
||||||
|
alt="Ray Template"
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
src="https://r2chevereto.yka.moe/longmao.navigator.th.png"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="https://nodejs.org/en/about/previous-releases"><img src="https://img.shields.io/node/v/vite.svg" alt="node compatibility"></a>
|
||||||
|
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/LICENSE"
|
||||||
|
><img
|
||||||
|
src="https://img.shields.io/github/license/XiaoDaiGua-Ray/ray-template"
|
||||||
|
alt="LICENSE"
|
||||||
|
/></a>
|
||||||
|
<a href="#badge"><img src="https://img.shields.io/github/languages/top/XiaoDaiGua-Ray/ray-template" alt="language"></a>
|
||||||
|
<a href="https://www.npmjs.com/package/ray-template"><img src="https://img.shields.io/npm/v/ray-template" alt="npm package"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
@ -9,35 +25,43 @@
|
|||||||
|
|
||||||
English | [简体中文](https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/README-ZH.md)
|
English | [简体中文](https://github.com/XiaoDaiGua-Ray/ray-template/blob/main/README-ZH.md)
|
||||||
|
|
||||||
A `free`, `efficient`, `complete with features` middle and backend template based on the latest technologies such as vite5.x & ts(x) & pinia & vue3.x.
|
A `completely free`, `efficient`, `feature complete` and based on vite5. x & ts(x) & pinia & vue3. x and other latest technology in the background template.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## ✨ Feature
|
## 🌻 Intro
|
||||||
|
|
||||||
- **Power by love**: Contains almost all common template features on the market and all are free to use.
|
`Ray Template` uses cutting-edge front-end technology, abandoning complexity and bloat, using modular design, decoupling data, methods and views, focusing on business development. Provide rich configuration and rich template `Hooks`, support personalized customization, to meet your project needs.
|
||||||
- **Latest Technology Stack**:Developed using front-end cutting-edge technologies such as vue3.x/vite5.x/pinia.
|
|
||||||
- **TypeScript**:The language for application-level JavaScript.
|
|
||||||
- **App Theme**:Configurable themes.
|
|
||||||
- **Globalization**:Built-in complete internationalization solution.
|
|
||||||
- **Mock Data**:Built-in Mock data scheme.
|
|
||||||
- **Permissions**:Built-in complete dynamic routing permission generation solution.
|
|
||||||
- **Components**:Secondary encapsulation of multiple commonly used components.
|
|
||||||
- **Axios Request**:Secondary encapsulation of the axios library, supporting functions such as cancellation, anti-shake, automatic repeat cancellation, etc.
|
|
||||||
- **Page Cache**:Arbitrarily deep page cache.
|
|
||||||
- **SVG**:Built-in svg icon solution.
|
|
||||||
- **Standalone Data Methods Views**:Decoupled management of data, methods, and views allows for secondary development with confidence.
|
|
||||||
- **Template Specific Hooks** : Hooks based on the template feature package make it easier to use some of the features of the template.
|
|
||||||
|
|
||||||
## 🪄 Preview
|
## ✨ Features
|
||||||
|
|
||||||
- [Click to preview](https://xiaodaigua-ray.github.io/ray-template/#/)
|
- `New technology stack:` using ts(x), vite5. x, vue3. x, pinia and other front-end cutting-edge technology development
|
||||||
- [Click to preview(Acceleration address)](https://ray-template.yunkuangao.com/#/)
|
- `Theme:` configurable theme
|
||||||
|
- `Internationalization:` built-in perfect internationalization solution
|
||||||
|
- `Permissions:` built-in perfect dynamic routing permission generation solution
|
||||||
|
- `Components:` secondary encapsulation of multiple common components
|
||||||
|
- `Toolkit:` common tool function packaging
|
||||||
|
- `Cache:` arbitrary depth page caching
|
||||||
|
- `Modular design:` decoupling management data, methods, views, rest assured secondary development
|
||||||
|
- `Configurable:` support rich configuration items
|
||||||
|
- `Code style:` built-in prettier, eslint and other code style tools
|
||||||
|
- `Multi-terminal adaptation:` support pc, phone, pad
|
||||||
|
- `Documentation:` complete documentation
|
||||||
|
- `Mock data:` built-in Mock data solution
|
||||||
|
- `Axios request:` secondary encapsulation of axios library, support: cancel, jitter, automatic repeat cancellation and other functions
|
||||||
|
- `SVG:` built-in svg icon solution
|
||||||
|
- `Hooks:` based on the template characteristics of the encapsulated hooks to make it easier to use some functions of the template
|
||||||
|
- `TypeScript:` provide a complete type
|
||||||
|
|
||||||
## 🦾 Document
|
## 👀 Preview
|
||||||
|
|
||||||
- [Document](https://xiaodaigua-ray.github.io/ray-template-doc/)
|
- [Preview](https://xiaodaigua-ray.github.io/ray-template/#/)
|
||||||
- [Document(Acceleration address)](https://ray-template.yunkuangao.com/ray-template-doc/)
|
- [Preview(Acceleration address)](https://ray-template.yunkuangao.com/#/)
|
||||||
|
|
||||||
|
## 📌 Documentation
|
||||||
|
|
||||||
|
- [Documentation](https://xiaodaigua-ray.github.io/ray-template-doc/)
|
||||||
|
- [Documentation(Acceleration address)](https://ray-template.yunkuangao.com/ray-template-doc/)
|
||||||
|
|
||||||
## 🔋 Change Log
|
## 🔋 Change Log
|
||||||
|
|
||||||
@ -45,16 +69,17 @@ A `free`, `efficient`, `complete with features` middle and backend template base
|
|||||||
|
|
||||||
## 🪴 Prepare
|
## 🪴 Prepare
|
||||||
|
|
||||||
- [Node](http://nodejs.org/) and [git](https://git-scm.com/) - Project development environment
|
- [Node](http://nodejs.org/) and [git](https://git-scm.com/) - project development environment
|
||||||
- [Vite](https://vitejs.dev/) - Familiar with vite features
|
- [Vite](https://vitejs.dev/) - familiar with vite features
|
||||||
- [Vue3](https://v3.vuejs.org/) - Familiar with Vue3.x basic syntax
|
- [Vue3](https://v3.vuejs.org/) - familiar with Vue basic syntax
|
||||||
- [TypeScript](https://www.typescriptlang.org/) - Familiar with TypeScript basic syntax
|
- [TypeScript](https://www.typescriptlang.org/) - familiar with TypeScript basic syntax
|
||||||
- [Es6+](http://es6.ruanyifeng.com/) - Familiar with es6 basic syntax
|
- [Es6+](http://es6.ruanyifeng.com/) - familiar with es6 basic syntax
|
||||||
- [Vue-Router-Next](https://next.router.vuejs.org/) - Familiar with the basic use of vue-router4.x
|
- [Vue-Hooks-Plus] - familiar with vue-hooks-plus useRequest method basic use
|
||||||
- [Naive-UI](https://www.naiveui.com) - UI basic usage
|
- [Vue-Router-Next](https://next.router.vuejs.org/) - familiar with vue-router4.x basic use
|
||||||
- [Mock.js](https://github.com/nuysoft/Mock) - Mockjs basic syntax
|
- [Naive-UI](https://www.naiveui.com) - naive ui basic use
|
||||||
- [Pinia](https://pinia.vuejs.org/zh/introduction.html) - State manager pinia uses
|
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs basic syntax
|
||||||
- [TSX](https://github.com/vuejs/babel-plugin-jsx/blob/main/packages/babel-plugin-jsx/README-zh_CN.md) - TSX basic syntax
|
- [Pinia](https://pinia.vuejs.org/zh/introduction.html) - state manager pinia usage
|
||||||
|
- [TSX](https://github.com/vuejs/babel-plugin-jsx/blob/main/packages/babel-plugin-jsx/README-zh_CN.md) - tsx basic syntax
|
||||||
|
|
||||||
## 📦 Setup
|
## 📦 Setup
|
||||||
|
|
||||||
@ -80,7 +105,7 @@ pnpm i
|
|||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Project packaging
|
### Build project
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm build
|
pnpm build
|
||||||
@ -92,23 +117,23 @@ pnpm build
|
|||||||
pnpm preview
|
pnpm preview
|
||||||
```
|
```
|
||||||
|
|
||||||
### Volumetric analysis
|
### Report project
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm report
|
pnpm report
|
||||||
```
|
```
|
||||||
|
|
||||||
### Develop
|
### Development
|
||||||
|
|
||||||
Introduction and ease of use are the core ideas of this template. So you can safely delete all files under `views/demo` and `router/moduels/demo`, and you will have a clean project.
|
Just delete the files under `views/demo`, `router/modules/demo` to get a clean project template.
|
||||||
|
|
||||||
## 🪴 Project Activities
|
## 🪴 Project Activities
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Contributor
|
### Contributors
|
||||||
|
|
||||||
Thanks for all their contributions 🐝!
|
Thanks for all their contributions 🐝 !
|
||||||
|
|
||||||
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/graphs/contributors">
|
<a href="https://github.com/XiaoDaiGua-Ray/ray-template/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=XiaoDaiGua-Ray/ray-template" />
|
<img src="https://contrib.rocks/image?repo=XiaoDaiGua-Ray/ray-template" />
|
||||||
|
2
cfg.ts
2
cfg.ts
@ -42,7 +42,7 @@ import { htmlTitlePlugin, mixinCSSPlugin } from './vite-plugins/index'
|
|||||||
import { APP_THEME } from './src/app-config/designConfig'
|
import { APP_THEME } from './src/app-config/designConfig'
|
||||||
import { PRE_LOADING_CONFIG, SIDE_BAR_LOGO } from './src/app-config/appConfig'
|
import { PRE_LOADING_CONFIG, SIDE_BAR_LOGO } from './src/app-config/appConfig'
|
||||||
|
|
||||||
import type { AppConfigExport } from '@/types/modules/cfg'
|
import type { AppConfigExport } from '@/types'
|
||||||
import type { BuildOptions } from 'vite'
|
import type { BuildOptions } from 'vite'
|
||||||
|
|
||||||
const config: AppConfigExport = {
|
const config: AppConfigExport = {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
// style: 代码格式(不影响功能,例如空格、分号等格式修正) | Code format (no functional impact, such as space, semicolon, etc.)
|
// style: 代码格式(不影响功能,例如空格、分号等格式修正) | Code format (no functional impact, such as space, semicolon, etc.)
|
||||||
// version: 更新迭代 package.json 版本号 | Update the package.json version number
|
// version: 更新迭代 package.json 版本号 | Update the package.json version number
|
||||||
// build: 构建 | Build
|
// build: 构建 | Build
|
||||||
|
// plugin: 更新插件版本 | Update plugin version
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ignores: [(commit) => commit.includes('init')],
|
ignores: [(commit) => commit.includes('init')],
|
||||||
@ -33,6 +34,7 @@ module.exports = {
|
|||||||
'style',
|
'style',
|
||||||
'version',
|
'version',
|
||||||
'build',
|
'build',
|
||||||
|
'plugin',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
12
package.json
12
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ray-template",
|
"name": "ray-template",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "4.4.6",
|
"version": "4.5.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.0.0 || >=20.0.0",
|
"node": "^18.0.0 || >=20.0.0",
|
||||||
@ -44,11 +44,11 @@
|
|||||||
"interactjs": "1.10.26",
|
"interactjs": "1.10.26",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mockjs": "1.1.0",
|
"mockjs": "1.1.0",
|
||||||
"naive-ui": "^2.35.0",
|
"naive-ui": "^2.36.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.0",
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
"print-js": "^1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"vue": "^3.3.11",
|
"vue": "^3.4.0",
|
||||||
"vue-hooks-plus": "1.8.5",
|
"vue-hooks-plus": "1.8.5",
|
||||||
"vue-i18n": "^9.8.0",
|
"vue-i18n": "^9.8.0",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
@ -67,8 +67,8 @@
|
|||||||
"@types/mockjs": "1.0.7",
|
"@types/mockjs": "1.0.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
||||||
"@typescript-eslint/parser": "^6.5.0",
|
"@typescript-eslint/parser": "^6.5.0",
|
||||||
"@vitejs/plugin-vue": "^4.4.1",
|
"@vitejs/plugin-vue": "^5.0.0",
|
||||||
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||||
"@vue-hooks-plus/resolvers": "1.2.4",
|
"@vue-hooks-plus/resolvers": "1.2.4",
|
||||||
"@vue/eslint-config-prettier": "^8.0.0",
|
"@vue/eslint-config-prettier": "^8.0.0",
|
||||||
"@vue/eslint-config-typescript": "^11.0.3",
|
"@vue/eslint-config-typescript": "^11.0.3",
|
||||||
@ -93,7 +93,7 @@
|
|||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"unplugin-auto-import": "^0.16.6",
|
"unplugin-auto-import": "^0.16.6",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "^5.0.8",
|
"vite": "^5.0.10",
|
||||||
"vite-plugin-cdn2": "0.15.2",
|
"vite-plugin-cdn2": "0.15.2",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-ejs": "^1.7.0",
|
"vite-plugin-ejs": "^1.7.0",
|
||||||
|
928
pnpm-lock.yaml
generated
928
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -4,12 +4,14 @@ import AppStyleProvider from '@/app-components/provider/AppStyleProvider'
|
|||||||
import AppLockScreen from '@/app-components/app/AppLockScreen'
|
import AppLockScreen from '@/app-components/app/AppLockScreen'
|
||||||
import AppWatermarkProvider from '@/app-components/provider/AppWatermarkProvider'
|
import AppWatermarkProvider from '@/app-components/provider/AppWatermarkProvider'
|
||||||
import AppGlobalSpin from '@/spin'
|
import AppGlobalSpin from '@/spin'
|
||||||
|
import AppVersionProvider from '@/app-components/provider/AppVersionProvider'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'App',
|
name: 'App',
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<AppNaiveGlobalProvider>
|
<AppNaiveGlobalProvider>
|
||||||
|
<AppVersionProvider />
|
||||||
<AppLockScreen />
|
<AppLockScreen />
|
||||||
<AppStyleProvider />
|
<AppStyleProvider />
|
||||||
<AppWatermarkProvider />
|
<AppWatermarkProvider />
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { request } from '@/axios'
|
import { request } from '@/axios'
|
||||||
|
|
||||||
import type { BasicResponse, PaginationResponse } from '@/types/modules/axios'
|
import type { PaginationResponse } from '@/types'
|
||||||
|
|
||||||
export interface MockListParams {
|
export interface MockListParams {
|
||||||
page: number
|
page: number
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
import { request } from '@/axios'
|
import { request } from '@/axios'
|
||||||
|
|
||||||
import type { BasicResponse } from '@/types/modules/axios'
|
import type { BasicResponse } from '@/types'
|
||||||
|
|
||||||
interface AxiosTestResponse extends UnknownObjectKey {
|
interface AxiosTestResponse extends UnknownObjectKey {
|
||||||
data: UnknownObjectKey[]
|
data: UnknownObjectKey[]
|
||||||
|
@ -29,13 +29,7 @@ const AppRequestCancelerProvider = defineComponent({
|
|||||||
expose()
|
expose()
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <div class="app-style-provider"></div>
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: 'none',
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
* @remark 今天也是元气满满撸代码的一天
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './index.scss'
|
|
||||||
|
|
||||||
import { get } from 'lodash-es'
|
import { get } from 'lodash-es'
|
||||||
import {
|
import {
|
||||||
addClass,
|
addClass,
|
||||||
|
70
src/app-components/provider/AppVersionProvider/index.tsx
Normal file
70
src/app-components/provider/AppVersionProvider/index.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2024-01-01
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 检测当前版本是否为最新版本
|
||||||
|
* 如果不是最新版本则弹出提示框,提示用户更新,点击确认后退出登录并且刷新资源
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { RModal } from '@/components'
|
||||||
|
|
||||||
|
import { getStorage, setStorage } from '@/utils'
|
||||||
|
import { useSigningActions } from '@/store'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'AppVersionProvider',
|
||||||
|
setup() {
|
||||||
|
const storageKey = 'appVersionProvider'
|
||||||
|
const {
|
||||||
|
pkg: { version },
|
||||||
|
} = __APP_CFG__
|
||||||
|
const cacheVersion = getStorage<string>(storageKey, 'localStorage')
|
||||||
|
const modalShow = ref(false)
|
||||||
|
const { logout } = useSigningActions()
|
||||||
|
|
||||||
|
if (version !== cacheVersion || !cacheVersion) {
|
||||||
|
modalShow.value = true
|
||||||
|
|
||||||
|
setStorage<string>(storageKey, version, 'localStorage')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
modalShow,
|
||||||
|
logout,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const { logout } = this
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="app-style-provider">
|
||||||
|
<RModal
|
||||||
|
v-model:show={this.modalShow}
|
||||||
|
closeOnEsc={false}
|
||||||
|
maskClosable={false}
|
||||||
|
preset="dialog"
|
||||||
|
closable={false}
|
||||||
|
title="发现新版本"
|
||||||
|
content="当前版本已更新,点击确认加载新版本~"
|
||||||
|
zIndex={999999999}
|
||||||
|
dad
|
||||||
|
positiveText="确认"
|
||||||
|
negativeText="取消"
|
||||||
|
onPositiveClick={logout}
|
||||||
|
onNegativeClick={() => {
|
||||||
|
this.modalShow = false
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -11,12 +11,8 @@
|
|||||||
|
|
||||||
/** 系统配置 */
|
/** 系统配置 */
|
||||||
|
|
||||||
import type {
|
import type { LayoutSideBarLogo, PreloadingConfig } from '@/types'
|
||||||
LayoutSideBarLogo,
|
import type { AppMenuConfig, AppKeepAlive } from '@/types'
|
||||||
PreloadingConfig,
|
|
||||||
RootRoute,
|
|
||||||
} from '@/types/modules/cfg'
|
|
||||||
import type { AppMenuConfig, AppKeepAlive } from '@/types/modules/appConfig'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -44,21 +40,6 @@ export const PRE_LOADING_CONFIG: PreloadingConfig = {
|
|||||||
titleColor: '#2d8cf0',
|
titleColor: '#2d8cf0',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 配置根路由信息
|
|
||||||
* 模板维护一个根路由 ROOT_ROUTE,所有的重定向操作、回到 Layout Root Path 操作都依赖该 path
|
|
||||||
*
|
|
||||||
* 该变量的值,会传递给 globalRootRoute
|
|
||||||
* 这么做也是为了能够在兼容老版本的模板,并且也是为了能够动态的维护根路由信息
|
|
||||||
*
|
|
||||||
* 有些时候,如果你希望动态的维护 Root Route 信息,可以使用 useAppRoot 方法
|
|
||||||
*/
|
|
||||||
export const ROOT_ROUTE: RootRoute = {
|
|
||||||
name: 'Dashboard',
|
|
||||||
path: '/dashboard',
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* icon: LOGO 图标, 依赖 `RIcon` 实现(如果为空则不会渲染图标)
|
* icon: LOGO 图标, 依赖 `RIcon` 实现(如果为空则不会渲染图标)
|
||||||
@ -111,19 +92,3 @@ export const APP_CATCH_KEY = {
|
|||||||
localeLanguage: 'localeLanguage',
|
localeLanguage: 'localeLanguage',
|
||||||
token: 'token',
|
token: 'token',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 系统水印配置
|
|
||||||
* 具体配置信息查看官网: https://www.naiveui.com/zh-CN/dark/components/watermark#API
|
|
||||||
*/
|
|
||||||
export const APP_WATERMARK_CONFIG = {
|
|
||||||
content: 'Trying be better~',
|
|
||||||
fontSize: 16,
|
|
||||||
lineHeight: 16,
|
|
||||||
width: 384,
|
|
||||||
height: 384,
|
|
||||||
xOffset: 12,
|
|
||||||
yOffset: 60,
|
|
||||||
rotate: -15,
|
|
||||||
} as const
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
/** 系统颜色风格配置入口 */
|
/** 系统颜色风格配置入口 */
|
||||||
|
|
||||||
import type { AppTheme } from '@/types/modules/cfg'
|
import type { AppTheme } from '@/types'
|
||||||
|
|
||||||
export const APP_THEME: AppTheme = {
|
export const APP_THEME: AppTheme = {
|
||||||
/**
|
/**
|
||||||
@ -65,6 +65,8 @@ export const APP_THEME: AppTheme = {
|
|||||||
*
|
*
|
||||||
* 配置 echart 主题颜色
|
* 配置 echart 主题颜色
|
||||||
* 约定配置时以:主题名称为文件名,其文件夹下两个主题风格的 json 文件。并且暗色主题必须为 xxx-dark.json
|
* 约定配置时以:主题名称为文件名,其文件夹下两个主题风格的 json 文件。并且暗色主题必须为 xxx-dark.json
|
||||||
|
*
|
||||||
|
* [文档地址](https://xiaodaigua-ray.github.io/ray-template-doc/ray-template-docs/advanced/echart-themes.html)
|
||||||
*/
|
*/
|
||||||
echartTheme: 'macarons',
|
echartTheme: 'macarons',
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,8 @@
|
|||||||
|
|
||||||
/** 国际化相关配置 */
|
/** 国际化相关配置 */
|
||||||
|
|
||||||
import type {
|
import type { TemplateLocale, LocalOptions, DayjsLocalMap } from '@/types'
|
||||||
TemplateLocale,
|
import type { ValueOf } from '@/types'
|
||||||
LocalOptions,
|
|
||||||
DayjsLocalMap,
|
|
||||||
} from '@/types/modules/appConfig'
|
|
||||||
import type { ValueOf } from '@/types/modules/helper'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* @remark 今天也是元气满满撸代码的一天
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AxiosConfig } from '@/types/modules/appConfig'
|
import type { AxiosConfig } from '@/types'
|
||||||
|
|
||||||
/** axios 相关配置 */
|
/** axios 相关配置 */
|
||||||
export const AXIOS_CONFIG: AxiosConfig = {
|
export const AXIOS_CONFIG: AxiosConfig = {
|
||||||
|
@ -32,7 +32,7 @@ import type {
|
|||||||
AxiosFetchInstance,
|
AxiosFetchInstance,
|
||||||
AxiosFetchError,
|
AxiosFetchError,
|
||||||
} from '@/axios/type'
|
} from '@/axios/type'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
/** 当前请求的实例 */
|
/** 当前请求的实例 */
|
||||||
const axiosFetchInstance: AxiosFetchInstance = {
|
const axiosFetchInstance: AxiosFetchInstance = {
|
||||||
|
@ -30,7 +30,7 @@ import type {
|
|||||||
BeforeFetchFunction,
|
BeforeFetchFunction,
|
||||||
FetchErrorFunction,
|
FetchErrorFunction,
|
||||||
} from '@/axios/type'
|
} from '@/axios/type'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -27,7 +27,7 @@ import type {
|
|||||||
BeforeFetchFunction,
|
BeforeFetchFunction,
|
||||||
FetchErrorFunction,
|
FetchErrorFunction,
|
||||||
} from '@/axios/type'
|
} from '@/axios/type'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@ import type {
|
|||||||
Axios,
|
Axios,
|
||||||
AxiosResponse,
|
AxiosResponse,
|
||||||
} from 'axios'
|
} from 'axios'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
export type AxiosHeaderValue =
|
export type AxiosHeaderValue =
|
||||||
| AxiosHeaders
|
| AxiosHeaders
|
||||||
|
@ -49,7 +49,7 @@ import { RMoreDropdown } from '@/components'
|
|||||||
import { useSettingGetters } from '@/store'
|
import { useSettingGetters } from '@/store'
|
||||||
|
|
||||||
import type { WatchStopHandle } from 'vue'
|
import type { WatchStopHandle } from 'vue'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
import type { UseResizeObserverReturn } from '@vueuse/core'
|
import type { UseResizeObserverReturn } from '@vueuse/core'
|
||||||
import type { ECharts, EChartsCoreOption } from 'echarts/core'
|
import type { ECharts, EChartsCoreOption } from 'echarts/core'
|
||||||
@ -124,9 +124,7 @@ export default defineComponent({
|
|||||||
try {
|
try {
|
||||||
echarts.use(props.use?.filter(Boolean))
|
echarts.use(props.use?.filter(Boolean))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error('RChart register error: ', e)
|
||||||
'register chart Core error: wrong property and method passed in extend attribute',
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +247,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chart 是否已经销毁
|
||||||
const isDispose = () => !!(echartInst && echartInst.getDom())
|
const isDispose = () => !!(echartInst && echartInst.getDom())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,6 +269,14 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param key moreDropDownOptions key
|
||||||
|
* @param option moreDropDownOptions current click option
|
||||||
|
*
|
||||||
|
* 预设 card 风格下拉框点击
|
||||||
|
* 当前仅实现下载图片功能
|
||||||
|
*/
|
||||||
const dropdownSelect = (key: string | number, option: DropdownOption) => {
|
const dropdownSelect = (key: string | number, option: DropdownOption) => {
|
||||||
if (key === 'downloadChart' && isDispose()) {
|
if (key === 'downloadChart' && isDispose()) {
|
||||||
const { filename, ...args } = props.downloadOptions
|
const { filename, ...args } = props.downloadOptions
|
||||||
@ -303,7 +310,6 @@ export default defineComponent({
|
|||||||
if (props.autoResize) {
|
if (props.autoResize) {
|
||||||
resizeThrottleReturn = throttle(resizeChart, props.throttleWait)
|
resizeThrottleReturn = throttle(resizeChart, props.throttleWait)
|
||||||
/** 监听内容区域尺寸变化更新 chart */
|
/** 监听内容区域尺寸变化更新 chart */
|
||||||
|
|
||||||
resizeObserverReturn = useResizeObserver(
|
resizeObserverReturn = useResizeObserver(
|
||||||
props.observer || rayChartWrapperRef,
|
props.observer || rayChartWrapperRef,
|
||||||
resizeThrottleReturn,
|
resizeThrottleReturn,
|
||||||
@ -336,7 +342,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 贴花跟随主题渲染
|
* 贴花跟随主题渲染
|
||||||
@ -350,7 +355,6 @@ export default defineComponent({
|
|||||||
updateChartTheme()
|
updateChartTheme()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
/** 监听 options 变化 */
|
/** 监听 options 变化 */
|
||||||
if (props.watchOptions) {
|
if (props.watchOptions) {
|
||||||
@ -367,6 +371,7 @@ export default defineComponent({
|
|||||||
echartInst?.setOption(options, setOpt)
|
echartInst?.setOption(options, setOpt)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// 深度监听 options
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -383,6 +388,7 @@ export default defineComponent({
|
|||||||
echart: echartInstanceRef,
|
echart: echartInstanceRef,
|
||||||
dispose: unmount,
|
dispose: unmount,
|
||||||
render: mount,
|
render: mount,
|
||||||
|
isDispose,
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type * as echarts from 'echarts/core' // `echarts` 核心模块
|
import type * as echarts from 'echarts/core' // `echarts` 核心模块
|
||||||
import type { PropType, VNode } from 'vue'
|
import type { PropType, VNode } from 'vue'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
import type {
|
import type {
|
||||||
LoadingOptions,
|
LoadingOptions,
|
||||||
AutoResize,
|
AutoResize,
|
||||||
@ -52,6 +52,7 @@ const props = {
|
|||||||
type: Array as PropType<DropdownProps['options']>,
|
type: Array as PropType<DropdownProps['options']>,
|
||||||
},
|
},
|
||||||
preset: {
|
preset: {
|
||||||
|
// 是否启用预设样式
|
||||||
type: String as PropType<RChartPresetType>,
|
type: String as PropType<RChartPresetType>,
|
||||||
},
|
},
|
||||||
contentStyle: {
|
contentStyle: {
|
||||||
@ -153,6 +154,8 @@ const props = {
|
|||||||
*
|
*
|
||||||
* 拓展 `echarts` 图表
|
* 拓展 `echarts` 图表
|
||||||
* 用于自己手动拓展相关的包
|
* 用于自己手动拓展相关的包
|
||||||
|
*
|
||||||
|
* 注意,该方法不支持动态调用,及时动态更新了该属性,也不会生效
|
||||||
*/
|
*/
|
||||||
type: Array as PropType<EChartsExtensionInstallRegisters[]>,
|
type: Array as PropType<EChartsExtensionInstallRegisters[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
|
@ -2,7 +2,7 @@ import { gridProps } from 'naive-ui'
|
|||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { CollapseToggleText } from './type'
|
import type { CollapseToggleText } from './type'
|
||||||
import type { AnyFC, MaybeArray } from '@/types/modules/utils'
|
import type { AnyFC, MaybeArray } from '@/types'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
open: {
|
open: {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
color: {
|
color: {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
import type { SpinProps } from 'naive-ui'
|
import type { SpinProps } from 'naive-ui'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
@ -32,6 +32,11 @@ export default defineComponent({
|
|||||||
}))
|
}))
|
||||||
const uuidEl = uuid()
|
const uuidEl = uuid()
|
||||||
let intractable: null | ReturnType<typeof interact>
|
let intractable: null | ReturnType<typeof interact>
|
||||||
|
// 记录拖拽的位置
|
||||||
|
const position = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -44,7 +49,16 @@ export default defineComponent({
|
|||||||
const target = document.getElementById(uuidEl)
|
const target = document.getElementById(uuidEl)
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
setupDraggable(target, props.preset).then((res) => {
|
setupDraggable(target, props.preset, {
|
||||||
|
scheduler: (event) => {
|
||||||
|
const target = event.target
|
||||||
|
|
||||||
|
position.x += event.dx
|
||||||
|
position.y += event.dy
|
||||||
|
|
||||||
|
target.style.transform = `translate(${position.x}px, ${position.y}px)`
|
||||||
|
},
|
||||||
|
}).then((res) => {
|
||||||
intractable = res
|
intractable = res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -60,6 +74,12 @@ export default defineComponent({
|
|||||||
) {
|
) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setupInteract()
|
setupInteract()
|
||||||
|
|
||||||
|
const target = document.getElementById(uuidEl)
|
||||||
|
|
||||||
|
if (props.memo && target) {
|
||||||
|
target.style.transform = `translate(${position.x}px, ${position.y}px)`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
intractable?.unset()
|
intractable?.unset()
|
||||||
@ -67,6 +87,9 @@ export default defineComponent({
|
|||||||
intractable = null
|
intractable = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -13,6 +13,16 @@ import { modalProps } from 'naive-ui'
|
|||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
...modalProps,
|
...modalProps,
|
||||||
|
memo: {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 是否记住上一次的位置
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 是否全屏
|
* 是否全屏
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import interact from 'interactjs'
|
import interact from 'interactjs'
|
||||||
|
|
||||||
import type { ModalProps } from 'naive-ui'
|
import type { ModalProps } from 'naive-ui'
|
||||||
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
|
interface SetupDraggableOptions {
|
||||||
|
scheduler?: AnyFC
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -15,7 +20,10 @@ import type { ModalProps } from 'naive-ui'
|
|||||||
export const setupDraggable = (
|
export const setupDraggable = (
|
||||||
bindModal: HTMLElement,
|
bindModal: HTMLElement,
|
||||||
preset: ModalProps['preset'],
|
preset: ModalProps['preset'],
|
||||||
|
options?: SetupDraggableOptions,
|
||||||
): Promise<ReturnType<typeof interact>> => {
|
): Promise<ReturnType<typeof interact>> => {
|
||||||
|
const { scheduler } = options ?? {}
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const allowFromStr =
|
const allowFromStr =
|
||||||
@ -35,16 +43,7 @@ export const setupDraggable = (
|
|||||||
],
|
],
|
||||||
listeners: {
|
listeners: {
|
||||||
move: (event) => {
|
move: (event) => {
|
||||||
const target = event.target
|
scheduler?.(event)
|
||||||
const x =
|
|
||||||
(parseFloat(target.getAttribute('data-x')) || 0) + event.dx
|
|
||||||
const y =
|
|
||||||
(parseFloat(target.getAttribute('data-y')) || 0) + event.dy
|
|
||||||
|
|
||||||
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'
|
|
||||||
|
|
||||||
target.setAttribute('data-x', x)
|
|
||||||
target.setAttribute('data-y', y)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -23,4 +23,8 @@
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .n-spin-content--spinning img {
|
||||||
|
filter: blur(6px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,6 @@ export default defineComponent({
|
|||||||
const { expose } = ctx
|
const { expose } = ctx
|
||||||
|
|
||||||
const qrcodeURL = ref<QRCodeRenderResponse>()
|
const qrcodeURL = ref<QRCodeRenderResponse>()
|
||||||
const spinOverrides = {
|
|
||||||
opacitySpinning: '0.1',
|
|
||||||
}
|
|
||||||
let gifBuffer: GIFBuffer
|
let gifBuffer: GIFBuffer
|
||||||
let watchCallback!: WatchStopHandle
|
let watchCallback!: WatchStopHandle
|
||||||
|
|
||||||
@ -119,10 +116,12 @@ export default defineComponent({
|
|||||||
|
|
||||||
const downloadQRCode = (fileName?: DownloadFilenameType) => {
|
const downloadQRCode = (fileName?: DownloadFilenameType) => {
|
||||||
if (qrcodeURL.value && isValueType<string>(qrcodeURL.value, 'String')) {
|
if (qrcodeURL.value && isValueType<string>(qrcodeURL.value, 'String')) {
|
||||||
downloadAnyFile(
|
return downloadAnyFile(
|
||||||
qrcodeURL.value,
|
qrcodeURL.value,
|
||||||
fileName || new Date().getTime() + '.png',
|
fileName || new Date().getTime() + '.png',
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return Promise.reject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +150,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
qrcodeURL,
|
qrcodeURL,
|
||||||
spinOverrides,
|
|
||||||
errorActionClick,
|
errorActionClick,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -160,7 +158,6 @@ export default defineComponent({
|
|||||||
<div class="ray-qrcode">
|
<div class="ray-qrcode">
|
||||||
<NSpin
|
<NSpin
|
||||||
show={this.status === 'loading'}
|
show={this.status === 'loading'}
|
||||||
themeOverrides={this.spinOverrides}
|
|
||||||
description={this.loadingDescription}
|
description={this.loadingDescription}
|
||||||
>
|
>
|
||||||
<img src={this.qrcodeURL as string | undefined} />
|
<img src={this.qrcodeURL as string | undefined} />
|
||||||
@ -180,7 +177,7 @@ export default defineComponent({
|
|||||||
this.$slots.errorAction()
|
this.$slots.errorAction()
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<NButton text>
|
<NButton text type="primary" color="#ffffff">
|
||||||
{{
|
{{
|
||||||
default: () => this.errorActionDescription,
|
default: () => this.errorActionDescription,
|
||||||
icon: () => (
|
icon: () => (
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
import type { QRCodeStatus, QRCodeLevel } from './type'
|
import type { QRCodeStatus, QRCodeLevel } from './type'
|
||||||
import type { PropType, VNode } from 'vue'
|
import type { PropType, VNode } from 'vue'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
import type { Options } from 'awesome-qr'
|
import type { Options } from 'awesome-qr'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
@ -22,7 +22,7 @@ import { call, renderNode, uuid } from '@/utils'
|
|||||||
import config from './config'
|
import config from './config'
|
||||||
|
|
||||||
import type { DropdownOption, DataTableInst } from 'naive-ui'
|
import type { DropdownOption, DataTableInst } from 'naive-ui'
|
||||||
import type { ComponentSize } from '@/types/modules/component'
|
import type { ComponentSize } from '@/types'
|
||||||
import type { C as CType } from './type'
|
import type { C as CType } from './type'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -27,8 +27,8 @@ import { call } from '@/utils'
|
|||||||
|
|
||||||
import type { TreeOption, TreeDropInfo } from 'naive-ui'
|
import type { TreeOption, TreeDropInfo } from 'naive-ui'
|
||||||
import type { C } from '../type'
|
import type { C } from '../type'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
|
|
||||||
type FixedClick = (type: 'left' | 'right', option: C, index: number) => void
|
type FixedClick = (type: 'left' | 'right', option: C, index: number) => void
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ import { call } from '@/utils'
|
|||||||
import props from '../props'
|
import props from '../props'
|
||||||
import config from '../config'
|
import config from '../config'
|
||||||
|
|
||||||
import type { ComponentSize } from '@/types/modules/component'
|
import type { ComponentSize } from '@/types'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TableSizeSelect',
|
name: 'TableSizeSelect',
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
import { dataTableProps } from 'naive-ui'
|
import { dataTableProps } from 'naive-ui'
|
||||||
|
|
||||||
import type { PropType, VNode, VNodeChild } from 'vue'
|
import type { PropType, VNode, VNodeChild } from 'vue'
|
||||||
import type { MaybeArray } from '@/types/modules/utils'
|
import type { MaybeArray } from '@/types'
|
||||||
import type { DropdownOption, DataTableColumn } from 'naive-ui'
|
import type { DropdownOption, DataTableColumn } from 'naive-ui'
|
||||||
import type { DownloadTableOptions, PrintTableOptions } from './type'
|
import type { DownloadTableOptions, PrintTableOptions } from './type'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
...dataTableProps,
|
...dataTableProps,
|
||||||
|
@ -8,7 +8,7 @@ import type {
|
|||||||
DataTableBaseColumn,
|
DataTableBaseColumn,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import type { VNode } from 'vue'
|
import type { VNode } from 'vue'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
import type { PrintDomOptions } from '@/utils'
|
import type { PrintDomOptions } from '@/utils'
|
||||||
|
|
||||||
export type TableActionIcon = string | (() => VNode)
|
export type TableActionIcon = string | (() => VNode)
|
||||||
|
@ -18,7 +18,7 @@ import { debounce } from 'lodash-es'
|
|||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
|
||||||
import type { DebounceBindingOptions } from './type'
|
import type { DebounceBindingOptions } from './type'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
import type { CustomDirectiveFC } from '@/directives/type'
|
import type { CustomDirectiveFC } from '@/directives/type'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { DebounceSettings } from 'lodash-es'
|
import type { DebounceSettings } from 'lodash-es'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
export interface DebounceBindingOptions {
|
export interface DebounceBindingOptions {
|
||||||
func: AnyFC
|
func: AnyFC
|
||||||
|
@ -18,7 +18,7 @@ import { throttle } from 'lodash-es'
|
|||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
|
||||||
import type { ThrottleBindingOptions } from './type'
|
import type { ThrottleBindingOptions } from './type'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
import type { CustomDirectiveFC } from '@/directives/type'
|
import type { CustomDirectiveFC } from '@/directives/type'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { ThrottleSettings } from 'lodash-es'
|
import type { ThrottleSettings } from 'lodash-es'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
export interface ThrottleBindingOptions {
|
export interface ThrottleBindingOptions {
|
||||||
func: AnyFC
|
func: AnyFC
|
||||||
|
@ -27,11 +27,7 @@
|
|||||||
* createVariableState({ your state })
|
* createVariableState({ your state })
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ROOT_ROUTE, APP_WATERMARK_CONFIG } from '@/app-config/appConfig'
|
import type { AnyFC } from '@/types'
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
|
||||||
import type { Mutable } from '@/types/modules/helper'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -47,7 +43,6 @@ const variableState = reactive({
|
|||||||
globalDrawerValue: false, // 全局抽屉控制器(小尺寸设备可用)
|
globalDrawerValue: false, // 全局抽屉控制器(小尺寸设备可用)
|
||||||
globalMainLayoutLoad: true, // LayoutContent 区域加载控制器,会触发强制刷新
|
globalMainLayoutLoad: true, // LayoutContent 区域加载控制器,会触发强制刷新
|
||||||
layoutContentMaximize: false, // LayoutContent 区域全屏控制器
|
layoutContentMaximize: false, // LayoutContent 区域全屏控制器
|
||||||
globalRootRoute: cloneDeep(ROOT_ROUTE), // 全局根路由配置,同步至 ROOT_ROUTE
|
|
||||||
layoutContentSpinning: false, // LayoutContent 区域加载控制器,不会触发强制刷新
|
layoutContentSpinning: false, // LayoutContent 区域加载控制器,不会触发强制刷新
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -11,11 +11,10 @@
|
|||||||
|
|
||||||
import { useEventListener, onClickOutside } from '@vueuse/core'
|
import { useEventListener, onClickOutside } from '@vueuse/core'
|
||||||
|
|
||||||
import type { BasicTarget } from '@/types/modules/vue'
|
import type { BasicTarget } from '@/types'
|
||||||
import type {
|
import type {
|
||||||
MaybeElementRef,
|
MaybeElementRef,
|
||||||
MaybeElement,
|
MaybeElement,
|
||||||
UseEventSourceOptions,
|
|
||||||
MaybeRefOrGetter,
|
MaybeRefOrGetter,
|
||||||
} from '@vueuse/core'
|
} from '@vueuse/core'
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
import { useMenuGetters, useMenuActions } from '@/store'
|
import { useMenuGetters, useMenuActions } from '@/store'
|
||||||
|
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export type Target = number | AppMenuOption
|
export type Target = number | AppMenuOption
|
||||||
|
|
||||||
|
@ -9,29 +9,29 @@
|
|||||||
* @remark 今天也是元气满满撸代码的一天
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { setVariable, getVariableToRefs } from '@/global-variable'
|
import { useSettingGetters, useSettingActions } from '@/store'
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
import type { DeepMutable } from '@/types/modules/helper'
|
import type { AppRootRoute } from '@/store/modules/setting/type'
|
||||||
|
|
||||||
export function useAppRoot() {
|
export function useAppRoot() {
|
||||||
const globalRootRoute = getVariableToRefs('globalRootRoute')
|
const { getAppRootRoute } = useSettingGetters()
|
||||||
|
const { updateSettingState } = useSettingActions()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @remark 获取根路由
|
* @remark 获取根路由
|
||||||
*/
|
*/
|
||||||
const getRootRoute = computed(() => globalRootRoute.value)
|
const getRootRoute = getAppRootRoute
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @remark 获取根路由 path
|
* @remark 获取根路由 path
|
||||||
*/
|
*/
|
||||||
const getRootPath = computed(() => globalRootRoute.value.path)
|
const getRootPath = computed(() => getAppRootRoute.value.path)
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @remark 获取根路由 name
|
* @remark 获取根路由 name
|
||||||
*/
|
*/
|
||||||
const getRootName = computed(() => globalRootRoute.value.name)
|
const getRootName = computed(() => getAppRootRoute.value.name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -42,11 +42,11 @@ export function useAppRoot() {
|
|||||||
* @example
|
* @example
|
||||||
* setRootRoute({ path: '/your root path', name: 'your root name' })
|
* setRootRoute({ path: '/your root path', name: 'your root name' })
|
||||||
*/
|
*/
|
||||||
const setRootRoute = (route: DeepMutable<typeof globalRootRoute.value>) => {
|
const setRootRoute = (route: AppRootRoute) => {
|
||||||
const routeRef = getVariableToRefs('globalRootRoute')
|
updateSettingState(
|
||||||
const assignRoute = Object.assign(cloneDeep(routeRef.value), route)
|
'appRootRoute',
|
||||||
|
Object.assign({}, getAppRootRoute.value, route),
|
||||||
setVariable('globalRootRoute', assignRoute)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
import { useMenuGetters, useMenuActions } from '@/store'
|
import { useMenuGetters, useMenuActions } from '@/store'
|
||||||
import { redirectRouterToDashboard } from '@/router/helper/routerCopilot'
|
import { redirectRouterToDashboard } from '@/router/helper/routerCopilot'
|
||||||
|
|
||||||
import type { MenuTagOptions, Key } from '@/types/modules/app'
|
import type { MenuTagOptions, Key } from '@/types'
|
||||||
|
|
||||||
export type CloseMenuTag = Key | MenuTagOptions
|
export type CloseMenuTag = Key | MenuTagOptions
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
import { watchEffectWithTarget } from '@/utils'
|
import { watchEffectWithTarget } from '@/utils'
|
||||||
|
|
||||||
|
import type { UseWindowSizeOptions } from '@vueuse/core'
|
||||||
|
|
||||||
|
export interface UseDeviceOptions extends UseWindowSizeOptions {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 检测当前尺寸是否为平板或者更小
|
* 检测当前尺寸是否为平板或者更小
|
||||||
@ -28,8 +32,8 @@ import { watchEffectWithTarget } from '@/utils'
|
|||||||
* isTabletOrSmaller.value => true // 当前尺寸为平板或者更小
|
* isTabletOrSmaller.value => true // 当前尺寸为平板或者更小
|
||||||
* isTabletOrSmaller.value => false // 当前尺寸为桌面或者更大
|
* isTabletOrSmaller.value => false // 当前尺寸为桌面或者更大
|
||||||
*/
|
*/
|
||||||
export function useDevice() {
|
export function useDevice(options?: UseDeviceOptions) {
|
||||||
const { width, height } = useWindowSize()
|
const { width, height } = useWindowSize(options)
|
||||||
const isTabletOrSmaller = ref(false)
|
const isTabletOrSmaller = ref(false)
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
|
@ -13,7 +13,7 @@ import domToImage from 'dom-to-image'
|
|||||||
import { unrefElement } from '@/utils'
|
import { unrefElement } from '@/utils'
|
||||||
|
|
||||||
import type { Options as ReDomToImageOptions } from 'dom-to-image'
|
import type { Options as ReDomToImageOptions } from 'dom-to-image'
|
||||||
import type { BasicTarget, TargetType } from '@/types/modules/vue'
|
import type { BasicTarget, TargetType } from '@/types'
|
||||||
|
|
||||||
export type ImageType = keyof typeof domToImageMethods
|
export type ImageType = keyof typeof domToImageMethods
|
||||||
|
|
||||||
@ -90,7 +90,8 @@ const domToImageMethods = {
|
|||||||
* const { create, stop } = useDomToImage(refDom, {
|
* const { create, stop } = useDomToImage(refDom, {
|
||||||
* beforeCreate: (element) => { ... },
|
* beforeCreate: (element) => { ... },
|
||||||
* created: (element, result) => { ... },
|
* created: (element, result) => { ... },
|
||||||
* createdError: (element, error) => { ... },
|
* createdError: (error) => { ... },
|
||||||
|
* finally: () => { ... },
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
export const useDomToImage = <T extends HTMLElement>(
|
export const useDomToImage = <T extends HTMLElement>(
|
||||||
@ -102,10 +103,11 @@ export const useDomToImage = <T extends HTMLElement>(
|
|||||||
created,
|
created,
|
||||||
createdError,
|
createdError,
|
||||||
finally: _finally,
|
finally: _finally,
|
||||||
|
imageType: _imageType,
|
||||||
} = options ?? {}
|
} = options ?? {}
|
||||||
|
|
||||||
const run = (
|
const run = (
|
||||||
imageType: UseDomToImageOptions['imageType'] = 'jpeg',
|
imageType?: UseDomToImageOptions['imageType'],
|
||||||
): Promise<DomToImageResult> => {
|
): Promise<DomToImageResult> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const element = unrefElement(target)
|
const element = unrefElement(target)
|
||||||
@ -118,10 +120,7 @@ export const useDomToImage = <T extends HTMLElement>(
|
|||||||
return reject('useDomToImage: element is undefined.')
|
return reject('useDomToImage: element is undefined.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = imageType ?? options?.imageType
|
domToImageMethods[imageType ?? _imageType ?? 'jpeg']?.(element, options)
|
||||||
const matchFc = domToImageMethods[type] || domToImageMethods['jpeg']
|
|
||||||
|
|
||||||
matchFc(element, options)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
created?.(res, element)
|
created?.(res, element)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
import { unrefElement, effectDispose, isValueType } from '@/utils'
|
import { unrefElement, effectDispose, isValueType } from '@/utils'
|
||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
|
|
||||||
import type { BasicTarget } from '@/types/modules/vue'
|
import type { BasicTarget } from '@/types'
|
||||||
|
|
||||||
export interface UseElementFullscreenOptions {
|
export interface UseElementFullscreenOptions {
|
||||||
beforeEnter?: () => void
|
beforeEnter?: () => void
|
||||||
@ -159,3 +159,7 @@ export const useElementFullscreen = (
|
|||||||
toggleFullscreen,
|
toggleFullscreen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UseElementFullscreenReturnTypes = ReturnType<
|
||||||
|
typeof useElementFullscreen
|
||||||
|
>
|
||||||
|
@ -18,7 +18,7 @@ const getI18nKey = (namespace: string | undefined, key: string) => {
|
|||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.startsWith(namespace)) {
|
if (key[0] === namespace) {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import print from 'print-js'
|
import print from 'print-js'
|
||||||
import { unrefElement } from '@/utils'
|
import { unrefElement } from '@/utils'
|
||||||
|
|
||||||
import type { BasicTarget } from '@/types/modules/vue'
|
import type { BasicTarget } from '@/types'
|
||||||
|
|
||||||
export interface UsePrintOptions
|
export interface UsePrintOptions
|
||||||
extends Omit<print.Configuration, 'printable'> {}
|
extends Omit<print.Configuration, 'printable'> {}
|
||||||
|
@ -20,8 +20,8 @@ import { getVariableToRefs, setVariable } from '@/global-variable'
|
|||||||
import { useMenuGetters, useMenuActions } from '@/store'
|
import { useMenuGetters, useMenuActions } from '@/store'
|
||||||
|
|
||||||
import type { MenuInst } from 'naive-ui'
|
import type { MenuInst } from 'naive-ui'
|
||||||
import type { NaiveMenuOptions } from '@/types/modules/component'
|
import type { NaiveMenuOptions } from '@/types'
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'AppMenu',
|
name: 'AppMenu',
|
||||||
|
@ -52,7 +52,7 @@ import { throttle } from 'lodash-es'
|
|||||||
import { useAppRoot } from '@/hooks/template'
|
import { useAppRoot } from '@/hooks/template'
|
||||||
|
|
||||||
import type { ScrollbarInst } from 'naive-ui'
|
import type { ScrollbarInst } from 'naive-ui'
|
||||||
import type { MenuTagOptions, AppMenuOption } from '@/types/modules/app'
|
import type { MenuTagOptions, AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'AppMenuTag',
|
name: 'AppMenuTag',
|
||||||
@ -423,7 +423,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const { iconConfig, getRootPath, uuidScrollBar } = this
|
const { iconConfig, getRootPath, uuidScrollBar, getMenuTagOptions } = this
|
||||||
const { maximize, closeCurrentMenuTag, scrollX, $t } = this
|
const { maximize, closeCurrentMenuTag, scrollX, $t } = this
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -472,7 +472,7 @@ export default defineComponent({
|
|||||||
align="center"
|
align="center"
|
||||||
justify="start"
|
justify="start"
|
||||||
>
|
>
|
||||||
{this.getMenuTagOptions.map((curr, idx) => (
|
{getMenuTagOptions.map((curr, idx) => (
|
||||||
<NButton
|
<NButton
|
||||||
key={curr.key}
|
key={curr.key}
|
||||||
class={['menu-tag__btn']}
|
class={['menu-tag__btn']}
|
||||||
@ -502,8 +502,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
{(curr.closeable ||
|
{(curr.closeable || getMenuTagOptions.length === 1) &&
|
||||||
this.getMenuTagOptions.length === 1) &&
|
|
||||||
curr.key !== getRootPath ? (
|
curr.key !== getRootPath ? (
|
||||||
<NIcon
|
<NIcon
|
||||||
class="menu-tag__btn-icon"
|
class="menu-tag__btn-icon"
|
||||||
|
@ -27,7 +27,7 @@ import { useMenuGetters, useMenuActions } from '@/store'
|
|||||||
import { useDevice } from '@/hooks/web'
|
import { useDevice } from '@/hooks/web'
|
||||||
|
|
||||||
import type { DropdownOption } from 'naive-ui'
|
import type { DropdownOption } from 'naive-ui'
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SiderBarBreadcrumb',
|
name: 'SiderBarBreadcrumb',
|
||||||
|
@ -31,7 +31,7 @@ import { useDevice } from '@/hooks/web'
|
|||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
|
||||||
import type { AppRouteMeta } from '@/router/type'
|
import type { AppRouteMeta } from '@/router/type'
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'GlobalSearch',
|
name: 'GlobalSearch',
|
||||||
|
@ -27,7 +27,7 @@ import { APP_THEME } from '@/app-config/designConfig'
|
|||||||
import { useSettingGetters, useSettingActions } from '@/store'
|
import { useSettingGetters, useSettingActions } from '@/store'
|
||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { Placement } from '@/types/modules/component'
|
import type { Placement } from '@/types'
|
||||||
|
|
||||||
const SettingDrawer = defineComponent({
|
const SettingDrawer = defineComponent({
|
||||||
name: 'SettingDrawer',
|
name: 'SettingDrawer',
|
||||||
|
@ -22,7 +22,7 @@ import { getStorage } from '@/utils'
|
|||||||
import { SYSTEM_DEFAULT_LOCAL } from '@/app-config/localConfig'
|
import { SYSTEM_DEFAULT_LOCAL } from '@/app-config/localConfig'
|
||||||
import { APP_CATCH_KEY } from '@/app-config/appConfig'
|
import { APP_CATCH_KEY } from '@/app-config/appConfig'
|
||||||
|
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
import type {
|
import type {
|
||||||
AppLocalesModules,
|
AppLocalesModules,
|
||||||
AppLocalesDropdownMixedOption,
|
AppLocalesDropdownMixedOption,
|
||||||
|
@ -4,7 +4,7 @@ import type {
|
|||||||
DropdownDividerOption,
|
DropdownDividerOption,
|
||||||
DropdownRenderOption,
|
DropdownRenderOption,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
export interface AppCurrentAppMessages {
|
export interface AppCurrentAppMessages {
|
||||||
'zh-CN': object
|
'zh-CN': object
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
import '@/styles/base.scss'
|
import '@/styles/base.scss'
|
||||||
|
import './app-components/provider/provider.scss'
|
||||||
|
|
||||||
import 'virtual:svg-icons-register' // vite-plugin-svg-icons 脚本,启用 svg 雪碧图
|
import 'virtual:svg-icons-register' // vite-plugin-svg-icons 脚本,启用 svg 雪碧图
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ import { cloneDeep } from 'lodash-es'
|
|||||||
|
|
||||||
import type { AppRouteRecordRaw } from '@/router/type'
|
import type { AppRouteRecordRaw } from '@/router/type'
|
||||||
|
|
||||||
const isRootPath = (path: string) => path.startsWith('/')
|
// 是否为根路由
|
||||||
|
const isRootPath = (path: string) => path[0] === '/'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -41,31 +42,25 @@ const routePromotion = (
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const sourceArr = arr
|
for (const curr of arr) {
|
||||||
|
const newPath = path + (isRootPath(curr.path) ? curr.path : '/' + curr.path)
|
||||||
|
|
||||||
sourceArr.forEach((curr) => {
|
|
||||||
if (curr.children?.length) {
|
if (curr.children?.length) {
|
||||||
routePromotion(
|
routePromotion(curr.children, result, newPath)
|
||||||
curr.children,
|
|
||||||
result,
|
|
||||||
path + (isRootPath(curr.path) ? curr.path : '/' + curr.path),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
const newPath =
|
|
||||||
path + (isRootPath(curr.path) ? curr.path : '/' + curr.path)
|
|
||||||
|
|
||||||
const newCurr: AppRouteRecordRaw = {
|
continue
|
||||||
|
} else {
|
||||||
|
result.push({
|
||||||
...curr,
|
...curr,
|
||||||
path: newPath,
|
path: newPath,
|
||||||
}
|
})
|
||||||
|
|
||||||
result.push(newCurr)
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所有已展开的路由
|
||||||
export const expandRoutes = (arr: AppRouteRecordRaw[]) => {
|
export const expandRoutes = (arr: AppRouteRecordRaw[]) => {
|
||||||
if (!Array.isArray(arr)) {
|
if (!Array.isArray(arr)) {
|
||||||
return []
|
return []
|
||||||
|
@ -18,7 +18,7 @@ import { useAppRoot } from '@/hooks/template'
|
|||||||
|
|
||||||
import type { Router } from 'vue-router'
|
import type { Router } from 'vue-router'
|
||||||
import type { AppRouteMeta } from '@/router/type'
|
import type { AppRouteMeta } from '@/router/type'
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
import type { DefineComponent, VNode } from 'vue'
|
import type { DefineComponent, VNode } from 'vue'
|
||||||
|
|
||||||
export type Component<T = any> =
|
export type Component<T = any> =
|
||||||
|
@ -79,7 +79,6 @@ export const useMenuGetters = () => {
|
|||||||
export const useMenuActions = () => {
|
export const useMenuActions = () => {
|
||||||
const {
|
const {
|
||||||
changeMenuModelValue,
|
changeMenuModelValue,
|
||||||
setupAppMenu,
|
|
||||||
collapsedMenu,
|
collapsedMenu,
|
||||||
spliceMenTagOptions,
|
spliceMenTagOptions,
|
||||||
emptyMenuTagOptions,
|
emptyMenuTagOptions,
|
||||||
@ -88,7 +87,6 @@ export const useMenuActions = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
changeMenuModelValue,
|
changeMenuModelValue,
|
||||||
setupAppMenu,
|
|
||||||
collapsedMenu,
|
collapsedMenu,
|
||||||
spliceMenTagOptions,
|
spliceMenTagOptions,
|
||||||
emptyMenuTagOptions,
|
emptyMenuTagOptions,
|
||||||
|
@ -71,6 +71,12 @@ export const useSettingGetters = () => {
|
|||||||
*/
|
*/
|
||||||
const getWatermarkConfig = computed(() => variable.watermarkConfig)
|
const getWatermarkConfig = computed(() => variable.watermarkConfig)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @remark 获取 app 根路由
|
||||||
|
*/
|
||||||
|
const getAppRootRoute = computed(() => variable.appRootRoute)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDrawerPlacement,
|
getDrawerPlacement,
|
||||||
getPrimaryColorOverride,
|
getPrimaryColorOverride,
|
||||||
@ -83,6 +89,7 @@ export const useSettingGetters = () => {
|
|||||||
getContentTransition,
|
getContentTransition,
|
||||||
getWatermarkSwitch,
|
getWatermarkSwitch,
|
||||||
getWatermarkConfig,
|
getWatermarkConfig,
|
||||||
|
getAppRootRoute,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
import { APP_KEEP_ALIVE } from '@/app-config/appConfig'
|
import { APP_KEEP_ALIVE } from '@/app-config/appConfig'
|
||||||
|
|
||||||
import type { KeepAliveStoreState } from './type'
|
import type { KeepAliveStoreState } from './type'
|
||||||
import type { AppMenuOption } from '@/types/modules/app'
|
import type { AppMenuOption } from '@/types'
|
||||||
|
|
||||||
export const piniaKeepAliveStore = defineStore(
|
export const piniaKeepAliveStore = defineStore(
|
||||||
'keepAlive',
|
'keepAlive',
|
||||||
|
@ -39,11 +39,7 @@ const isMatch = (
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node[key] === value) {
|
return node[key] === value
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +91,7 @@ export const parseAndFindMatchingNodes = (
|
|||||||
key: string | number,
|
key: string | number,
|
||||||
value: string | number,
|
value: string | number,
|
||||||
) => {
|
) => {
|
||||||
const temp = []
|
const temp: AppMenuOption[] = []
|
||||||
|
|
||||||
for (const it of options) {
|
for (const it of options) {
|
||||||
const innerTemp = findMatchingNodes(it, key, value)
|
const innerTemp = findMatchingNodes(it, key, value)
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
import { NEllipsis } from 'naive-ui'
|
import { NEllipsis } from 'naive-ui'
|
||||||
|
|
||||||
import { setStorage } from '@/utils'
|
import { setStorage, pick } from '@/utils'
|
||||||
import { validRole, validMenuItemShow } from '@/router/helper/routerCopilot'
|
import { validRole, validMenuItemShow } from '@/router/helper/routerCopilot'
|
||||||
import {
|
import {
|
||||||
parseAndFindMatchingNodes,
|
parseAndFindMatchingNodes,
|
||||||
@ -35,18 +35,16 @@ import {
|
|||||||
} from './helper'
|
} from './helper'
|
||||||
import { useI18n } from '@/hooks/web'
|
import { useI18n } from '@/hooks/web'
|
||||||
import { getAppRawRoutes } from '@/router/appRouteModules'
|
import { getAppRawRoutes } from '@/router/appRouteModules'
|
||||||
import { throttle } from 'lodash-es'
|
|
||||||
import { useKeepAliveActions } from '@/store'
|
import { useKeepAliveActions } from '@/store'
|
||||||
|
|
||||||
import type { AppRouteRecordRaw } from '@/router/type'
|
import type { AppMenuOption, MenuTagOptions } from '@/types'
|
||||||
import type { AppMenuOption, MenuTagOptions } from '@/types/modules/app'
|
|
||||||
import type { MenuState } from '@/store/modules/menu/type'
|
import type { MenuState } from '@/store/modules/menu/type'
|
||||||
import type { LocationQuery } from 'vue-router'
|
import type { LocationQuery } from 'vue-router'
|
||||||
|
|
||||||
export const piniaMenuStore = defineStore(
|
export const piniaMenuStore = defineStore(
|
||||||
'menu',
|
'menu',
|
||||||
() => {
|
() => {
|
||||||
const router = useRouter()
|
const { push, getRoutes } = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { setKeepAliveInclude } = useKeepAliveActions()
|
const { setKeepAliveInclude } = useKeepAliveActions()
|
||||||
@ -86,8 +84,7 @@ export const piniaMenuStore = defineStore(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (option.path === getCatchMenuKey()) {
|
if (option.path === getCatchMenuKey()) {
|
||||||
/** 设置标签页(初始化时执行设置一次, 避免含有平级路由模式情况时出现不能正确设置标签页的情况) */
|
menuState.currentMenuOption = attr
|
||||||
setMenuTagOptionsWhenMenuValueChange(option.path, attr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.show = validMenuItemShow(attr)
|
attr.show = validMenuItemShow(attr)
|
||||||
@ -121,21 +118,7 @@ export const piniaMenuStore = defineStore(
|
|||||||
key: string | number,
|
key: string | number,
|
||||||
option: AppMenuOption,
|
option: AppMenuOption,
|
||||||
) => {
|
) => {
|
||||||
const { meta } = option as unknown as AppRouteRecordRaw
|
|
||||||
|
|
||||||
menuState.breadcrumbOptions = getCompleteRoutePath(menuState.options, key)
|
menuState.breadcrumbOptions = getCompleteRoutePath(menuState.options, key)
|
||||||
|
|
||||||
if (meta.sameLevel) {
|
|
||||||
nextTick().then(() => {
|
|
||||||
const fd = menuState.breadcrumbOptions.find((curr) => {
|
|
||||||
return curr.path === option.path
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!fd) {
|
|
||||||
menuState.breadcrumbOptions.push(option as unknown as AppMenuOption)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,46 +187,68 @@ export const piniaMenuStore = defineStore(
|
|||||||
*
|
*
|
||||||
* 但是, 缓存 key 都以当前点击 key 为准
|
* 但是, 缓存 key 都以当前点击 key 为准
|
||||||
*/
|
*/
|
||||||
if (!String(key).startsWith('/')) {
|
if (String(key)[0] === '/') {
|
||||||
|
/** 根路由直接跳转 */
|
||||||
|
push({
|
||||||
|
path,
|
||||||
|
query,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
/** 如果不是根路由, 则拼接完整路由并跳转 */
|
/** 如果不是根路由, 则拼接完整路由并跳转 */
|
||||||
const _path = getCompleteRoutePath(menuState.options, key)
|
const _path = getCompleteRoutePath(menuState.options, key)
|
||||||
.map((curr) => curr.key)
|
.map((curr) => curr.key)
|
||||||
.join('/')
|
.join('/')
|
||||||
|
|
||||||
router.push({
|
push({
|
||||||
path: _path,
|
path: _path,
|
||||||
query,
|
query,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
/** 根路由直接跳转 */
|
|
||||||
router.push({
|
|
||||||
path,
|
|
||||||
query,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 检查是否为根路由 */
|
/** 检查是否为根路由 */
|
||||||
const count = (path.match(isRootPathReg) || []).length
|
const count = (path.match(isRootPathReg) || []).length
|
||||||
|
const { sameLevel } = meta
|
||||||
|
|
||||||
/** 更新缓存队列 */
|
/** 更新缓存队列 */
|
||||||
setKeepAliveInclude(option as unknown as AppMenuOption)
|
setKeepAliveInclude(option)
|
||||||
/** 更新浏览器标题 */
|
/** 更新浏览器标题 */
|
||||||
updateDocumentTitle(option as unknown as AppMenuOption)
|
updateDocumentTitle(option)
|
||||||
|
|
||||||
if (!meta.sameLevel || (meta.sameLevel && count === 1)) {
|
// 如果不为 sameLevel,则会执行更新:覆盖更新面包屑、添加标签菜单、更新缓存
|
||||||
|
if (!sameLevel || (sameLevel && count === 1)) {
|
||||||
/** 更新标签菜单 */
|
/** 更新标签菜单 */
|
||||||
setMenuTagOptionsWhenMenuValueChange(key, option)
|
setMenuTagOptionsWhenMenuValueChange(key, option)
|
||||||
/** 更新面包屑 */
|
/** 更新面包屑 */
|
||||||
setBreadcrumbOptions(key, option)
|
setBreadcrumbOptions(key, option)
|
||||||
|
|
||||||
menuState.menuKey = key
|
menuState.menuKey = key
|
||||||
|
menuState.currentMenuOption = option
|
||||||
|
|
||||||
/** 缓存菜单 key(sessionStorage) */
|
/** 缓存菜单 key(sessionStorage) */
|
||||||
setStorage('menuKey', key)
|
setStorage('menuKey', key)
|
||||||
} else {
|
} else {
|
||||||
setBreadcrumbOptions(menuState.menuKey || '', option)
|
// 使用 pick 提取仅需要的字段,避免 vue 抛错空引用,导致性能损耗
|
||||||
}
|
const breadcrumbOption = pick(resolveOption(option), [
|
||||||
|
'breadcrumbLabel',
|
||||||
|
'children',
|
||||||
|
'key',
|
||||||
|
'meta',
|
||||||
|
'name',
|
||||||
|
'path',
|
||||||
|
'show',
|
||||||
|
])
|
||||||
|
// 查看是否重复
|
||||||
|
const find = menuState.breadcrumbOptions.find(
|
||||||
|
(curr) => curr.key === breadcrumbOption.key,
|
||||||
|
)
|
||||||
|
|
||||||
menuState.currentMenuOption = option
|
// 如果未重复追加
|
||||||
|
if (!find) {
|
||||||
|
menuState.breadcrumbOptions.push(
|
||||||
|
breadcrumbOption as unknown as AppMenuOption,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,21 +275,22 @@ export const piniaMenuStore = defineStore(
|
|||||||
combinePath = splitPath[splitPath.length - 1]
|
combinePath = splitPath[splitPath.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果当前菜单 key 与路由地址相同,说明不是手动更新 url, 则不会触发更新
|
// 直接使用完整 url,检查是否在 routes 中
|
||||||
if (combinePath === menuState.menuKey) {
|
const findMenuOption = getRoutes().find((curr) => curr.path === routePath)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const findMenuOption = router
|
|
||||||
.getRoutes()
|
|
||||||
.find((curr) =>
|
|
||||||
count > 1 ? path === curr.path : combinePath === curr.path,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (findMenuOption) {
|
if (findMenuOption) {
|
||||||
|
// 使用 pick 提取仅需要的字段,避免 vue 抛错空引用,导致性能损耗
|
||||||
|
const pickOption = pick(findMenuOption, [
|
||||||
|
'children',
|
||||||
|
'meta',
|
||||||
|
'path',
|
||||||
|
'name',
|
||||||
|
'redirect',
|
||||||
|
]) as unknown as AppMenuOption
|
||||||
|
|
||||||
changeMenuModelValue(
|
changeMenuModelValue(
|
||||||
count > 1 ? combinePath : path,
|
count > 1 ? combinePath : path,
|
||||||
resolveOption(findMenuOption as unknown as AppMenuOption),
|
resolveOption(pickOption),
|
||||||
query,
|
query,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -320,6 +326,17 @@ export const piniaMenuStore = defineStore(
|
|||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 初始化后更新面包屑、标签菜单
|
||||||
|
if (menuState.currentMenuOption) {
|
||||||
|
const { currentMenuOption } = menuState
|
||||||
|
|
||||||
|
setBreadcrumbOptions(currentMenuOption.key, currentMenuOption)
|
||||||
|
setMenuTagOptionsWhenMenuValueChange(
|
||||||
|
currentMenuOption.key,
|
||||||
|
currentMenuOption,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -384,8 +401,7 @@ export const piniaMenuStore = defineStore(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(menuState),
|
...toRefs(menuState),
|
||||||
changeMenuModelValue: throttle(changeMenuModelValue, 500),
|
changeMenuModelValue,
|
||||||
setupAppMenu,
|
|
||||||
collapsedMenu,
|
collapsedMenu,
|
||||||
spliceMenTagOptions,
|
spliceMenTagOptions,
|
||||||
emptyMenuTagOptions,
|
emptyMenuTagOptions,
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import type {
|
import type { AppMenuOption, MenuTagOptions, AppMenuKey } from '@/types'
|
||||||
AppMenuOption,
|
|
||||||
MenuTagOptions,
|
|
||||||
AppMenuKey,
|
|
||||||
} from '@/types/modules/app'
|
|
||||||
|
|
||||||
export interface MenuState {
|
export interface MenuState {
|
||||||
menuKey: AppMenuKey
|
menuKey: AppMenuKey
|
||||||
|
@ -4,12 +4,10 @@ import { colorToRgba, setStorage } from '@/utils'
|
|||||||
import { useI18n } from '@/hooks/web'
|
import { useI18n } from '@/hooks/web'
|
||||||
import { APP_THEME } from '@/app-config/designConfig'
|
import { APP_THEME } from '@/app-config/designConfig'
|
||||||
import { useDayjs } from '@/hooks/web'
|
import { useDayjs } from '@/hooks/web'
|
||||||
import { APP_WATERMARK_CONFIG } from '@/app-config/appConfig'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
import type { SettingState } from '@/store/modules/setting/type'
|
import type { SettingState } from '@/store/modules/setting/type'
|
||||||
import type { LocalKey } from '@/hooks/web'
|
import type { LocalKey } from '@/hooks/web'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
export const piniaSettingStore = defineStore(
|
export const piniaSettingStore = defineStore(
|
||||||
'setting',
|
'setting',
|
||||||
@ -37,7 +35,20 @@ export const piniaSettingStore = defineStore(
|
|||||||
copyrightSwitch: true, // 底部区域开关
|
copyrightSwitch: true, // 底部区域开关
|
||||||
contentTransition: 'scale', // 切换过渡效果
|
contentTransition: 'scale', // 切换过渡效果
|
||||||
watermarkSwitch: false, // 水印开关,
|
watermarkSwitch: false, // 水印开关,
|
||||||
watermarkConfig: cloneDeep(APP_WATERMARK_CONFIG),
|
watermarkConfig: {
|
||||||
|
content: 'Trying be better~',
|
||||||
|
fontSize: 16,
|
||||||
|
lineHeight: 16,
|
||||||
|
width: 384,
|
||||||
|
height: 384,
|
||||||
|
xOffset: 12,
|
||||||
|
yOffset: 60,
|
||||||
|
rotate: -15,
|
||||||
|
},
|
||||||
|
appRootRoute: {
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/dashboard',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 修改当前语言 */
|
/** 修改当前语言 */
|
||||||
|
@ -1,6 +1,21 @@
|
|||||||
import type { GlobalThemeOverrides } from 'naive-ui'
|
import type { GlobalThemeOverrides } from 'naive-ui'
|
||||||
import type { Placement } from '@/types/modules/component'
|
import type { Placement } from '@/types'
|
||||||
import type { APP_WATERMARK_CONFIG } from '@/app-config/appConfig'
|
|
||||||
|
export interface WatermarkConfig {
|
||||||
|
content: string
|
||||||
|
fontSize: number
|
||||||
|
lineHeight: number
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
xOffset: number
|
||||||
|
yOffset: number
|
||||||
|
rotate: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AppRootRoute {
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface SettingState {
|
export interface SettingState {
|
||||||
drawerPlacement: Placement
|
drawerPlacement: Placement
|
||||||
@ -13,5 +28,6 @@ export interface SettingState {
|
|||||||
watermarkSwitch: boolean
|
watermarkSwitch: boolean
|
||||||
copyrightSwitch: boolean
|
copyrightSwitch: boolean
|
||||||
contentTransition: string
|
contentTransition: string
|
||||||
watermarkConfig: typeof APP_WATERMARK_CONFIG
|
watermarkConfig: WatermarkConfig
|
||||||
|
appRootRoute: AppRootRoute
|
||||||
}
|
}
|
||||||
|
16
src/types/global.d.ts
vendored
16
src/types/global.d.ts
vendored
@ -8,12 +8,28 @@ import type {
|
|||||||
LoadingBarApi,
|
LoadingBarApi,
|
||||||
NotificationApi,
|
NotificationApi,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
|
import type { NativeElements, ReservedProps, VNode } from 'vue'
|
||||||
|
|
||||||
export declare global {
|
export declare global {
|
||||||
declare interface UnknownObjectKey {
|
declare interface UnknownObjectKey {
|
||||||
[propName: string]: any
|
[propName: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace JSX {
|
||||||
|
export interface Element extends VNode {}
|
||||||
|
export interface ElementClass {
|
||||||
|
$props: {}
|
||||||
|
}
|
||||||
|
export interface ElementAttributesProperty {
|
||||||
|
$props: {}
|
||||||
|
}
|
||||||
|
export interface IntrinsicElements extends NativeElements {
|
||||||
|
// allow arbitrary elements
|
||||||
|
[name: string]: any
|
||||||
|
}
|
||||||
|
export interface IntrinsicAttributes extends ReservedProps {}
|
||||||
|
}
|
||||||
|
|
||||||
declare const __DEV__: boolean
|
declare const __DEV__: boolean
|
||||||
|
|
||||||
declare const __APP_CFG__: AppConfig
|
declare const __APP_CFG__: AppConfig
|
||||||
|
8
src/types/index.ts
Normal file
8
src/types/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export type * from './modules/app'
|
||||||
|
export type * from './modules/appConfig'
|
||||||
|
export type * from './modules/axios'
|
||||||
|
export type * from './modules/cfg'
|
||||||
|
export type * from './modules/component'
|
||||||
|
export type * from './modules/helper'
|
||||||
|
export type * from './modules/utils'
|
||||||
|
export type * from './modules/vue'
|
@ -5,7 +5,7 @@ import type {
|
|||||||
AliasOptions,
|
AliasOptions,
|
||||||
UserConfigExport,
|
UserConfigExport,
|
||||||
} from 'vite'
|
} from 'vite'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
import type { GlobalThemeOverrides } from 'naive-ui'
|
import type { GlobalThemeOverrides } from 'naive-ui'
|
||||||
|
|
||||||
export interface LayoutSideBarLogo {
|
export interface LayoutSideBarLogo {
|
||||||
|
@ -13,6 +13,18 @@ export type ConditionalKeys<Base, Condition> = NonNullable<
|
|||||||
}[keyof Base]
|
}[keyof Base]
|
||||||
>
|
>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 从目标类型中排除符合条件的属性
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ConditionalExclude<{ a: string, b: number }, string> // { b: number }
|
||||||
|
*/
|
||||||
|
export type ConditionalExclude<Base, Condition> = Omit<
|
||||||
|
Base,
|
||||||
|
ConditionalKeys<Base, Condition>
|
||||||
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 从目标类型中挑选出符合条件的属性
|
* 从目标类型中挑选出符合条件的属性
|
||||||
@ -68,3 +80,17 @@ export type DeepMutable<T> = {
|
|||||||
? DeepMutable<T[P]>
|
? DeepMutable<T[P]>
|
||||||
: T[P]
|
: T[P]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 获取 Promise 返回值类型
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ReturnPromiseType<Promise<string>> // string
|
||||||
|
* ReturnPromiseType<Promise<string> | Promise<number>> // string | number
|
||||||
|
*/
|
||||||
|
export type ReturnPromiseType<T extends Promise<any>> = T extends Promise<
|
||||||
|
infer U
|
||||||
|
>
|
||||||
|
? U
|
||||||
|
: never
|
||||||
|
@ -3,8 +3,8 @@ import type {
|
|||||||
DownloadAnyFileDataType,
|
DownloadAnyFileDataType,
|
||||||
BasicTypes,
|
BasicTypes,
|
||||||
AnyFC,
|
AnyFC,
|
||||||
} from '@/types/modules/utils'
|
} from '@/types'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -150,9 +150,7 @@ export const downloadAnyFile = (
|
|||||||
try {
|
try {
|
||||||
if (typeof data === 'string') {
|
if (typeof data === 'string') {
|
||||||
downloadBase64File(data, fileName)
|
downloadBase64File(data, fileName)
|
||||||
resolve()
|
return resolve()
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data instanceof ArrayBuffer) {
|
if (data instanceof ArrayBuffer) {
|
||||||
@ -162,9 +160,7 @@ export const downloadAnyFile = (
|
|||||||
} else if (data instanceof File || data instanceof Blob) {
|
} else if (data instanceof File || data instanceof Blob) {
|
||||||
blobData = data
|
blobData = data
|
||||||
} else {
|
} else {
|
||||||
reject(new Error('downloadAnyFile: Unsupported data type.'))
|
return reject(new Error('downloadAnyFile: Unsupported data type.'))
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = URL.createObjectURL(blobData)
|
const url = URL.createObjectURL(blobData)
|
||||||
@ -181,18 +177,18 @@ export const downloadAnyFile = (
|
|||||||
|
|
||||||
link.addEventListener('load', () => {
|
link.addEventListener('load', () => {
|
||||||
remove()
|
remove()
|
||||||
resolve()
|
return resolve()
|
||||||
})
|
})
|
||||||
|
|
||||||
link.addEventListener('error', (error) => {
|
link.addEventListener('error', (error) => {
|
||||||
remove()
|
remove()
|
||||||
reject(error)
|
return reject(error)
|
||||||
})
|
})
|
||||||
|
|
||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click()
|
link.click()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error)
|
return reject(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* @remark 今天也是元气满满撸代码的一天
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { StorageLike, RemoveStorageKey } from '@/types/modules/utils'
|
import type { StorageLike, RemoveStorageKey } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// import MD5 from 'crypto-js/md5'
|
// import MD5 from 'crypto-js/md5'
|
||||||
// import BASE64 from 'crypto-js/enc-base64'
|
// import BASE64 from 'crypto-js/enc-base64'
|
||||||
|
|
||||||
// import type { WordArray, CipherParams } from '@/types/modules/utils'
|
// import type { WordArray, CipherParams } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -13,7 +13,7 @@ import { omit } from './basic'
|
|||||||
import { useDomToImage, usePrint } from '@/hooks/web'
|
import { useDomToImage, usePrint } from '@/hooks/web'
|
||||||
|
|
||||||
import type { UsePrintOptions, UseDomToImageOptions } from '@/hooks/web'
|
import type { UsePrintOptions, UseDomToImageOptions } from '@/hooks/web'
|
||||||
import type { BasicTarget } from '@/types/modules/vue'
|
import type { BasicTarget } from '@/types'
|
||||||
|
|
||||||
export interface PrintDomOptions {
|
export interface PrintDomOptions {
|
||||||
printOptions?: Omit<UsePrintOptions, 'printable' | 'type' | 'base64'>
|
printOptions?: Omit<UsePrintOptions, 'printable' | 'type' | 'base64'>
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { APP_REGEX } from '@/app-config/regexConfig'
|
import { APP_REGEX } from '@/app-config/regexConfig'
|
||||||
import { effectDispose, unrefElement, isValueType } from '@/utils'
|
import { effectDispose, unrefElement, isValueType } from '@/utils'
|
||||||
|
|
||||||
import type {
|
import type { PartialCSSStyleDeclaration, ElementSelector } from '@/types'
|
||||||
PartialCSSStyleDeclaration,
|
import type { BasicTarget } from '@/types'
|
||||||
ElementSelector,
|
|
||||||
} from '@/types/modules/utils'
|
|
||||||
import type { BasicTarget } from '@/types/modules/vue'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -32,7 +32,7 @@ import { cloneDeep } from 'lodash-es'
|
|||||||
import { isValueType } from '@/utils'
|
import { isValueType } from '@/utils'
|
||||||
|
|
||||||
import type { Options } from 'currency.js'
|
import type { Options } from 'currency.js'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
export type CurrencyArguments = string | number | currency
|
export type CurrencyArguments = string | number | currency
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import type { AnyFC, MaybeArray } from '@/types/modules/utils'
|
import type { AnyFC, MaybeArray } from '@/types'
|
||||||
|
|
||||||
function call(funcs: MaybeArray<() => void>): void
|
function call(funcs: MaybeArray<() => void>): void
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
import { getCurrentScope, onScopeDispose } from 'vue'
|
import { getCurrentScope, onScopeDispose } from 'vue'
|
||||||
|
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* @remark 今天也是元气满满撸代码的一天
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BasicTarget, TargetType, TargetValue } from '@/types/modules/vue'
|
import type { BasicTarget, TargetType, TargetValue } from '@/types'
|
||||||
import type { ComponentPublicInstance } from 'vue'
|
import type { ComponentPublicInstance } from 'vue'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
import { effectDispose } from './effectDispose'
|
import { effectDispose } from './effectDispose'
|
||||||
|
|
||||||
import type { WatchOptionsBase } from 'vue'
|
import type { WatchOptionsBase } from 'vue'
|
||||||
import type { AnyFC } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
NFormItem,
|
NFormItem,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
|
|
||||||
import type { ConditionalPick } from '@/types/modules/helper'
|
import type { ConditionalPick } from '@/types'
|
||||||
import type {
|
import type {
|
||||||
DebounceBindingOptions,
|
DebounceBindingOptions,
|
||||||
ThrottleBindingOptions,
|
ThrottleBindingOptions,
|
||||||
|
@ -28,6 +28,16 @@ export default defineComponent({
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<NSpace vertical wrapItem={false}>
|
<NSpace vertical wrapItem={false}>
|
||||||
|
<NCard title="props">
|
||||||
|
<NSpace vertical>
|
||||||
|
<h3>
|
||||||
|
memoryPosition: 是否记住上一次被拖拽的位置,如果设置为
|
||||||
|
true,那么下一次打开的时候会自动定位到上一次的位置。
|
||||||
|
</h3>
|
||||||
|
<h3>fullscreen: 全屏模态框。</h3>
|
||||||
|
<h3>dad: 启用拖拽,当配置为 false 时,会禁用拖拽效果。</h3>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
<RModal
|
<RModal
|
||||||
v-model:show={this.modal1}
|
v-model:show={this.modal1}
|
||||||
title="全屏模态框"
|
title="全屏模态框"
|
||||||
|
@ -58,7 +58,7 @@ export default defineComponent({
|
|||||||
logoImage={LOGO}
|
logoImage={LOGO}
|
||||||
status="error"
|
status="error"
|
||||||
onReload={() => {
|
onReload={() => {
|
||||||
window.$message.error('relod props')
|
window.$message.info('reload event')
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<RQRCode
|
<RQRCode
|
||||||
|
@ -69,7 +69,7 @@ const RouterDemoHome = defineComponent({
|
|||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
dataSource.push({
|
dataSource.push({
|
||||||
name: '张三',
|
name: '张三' + i,
|
||||||
address: 'New York No. 1 Lake Park',
|
address: 'New York No. 1 Lake Park',
|
||||||
phone: '010-121212',
|
phone: '010-121212',
|
||||||
key: i,
|
key: i,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"lib": ["ESNext", "DOM", "es5", "es6", "dom.iterable", "es2022"],
|
"lib": ["ESNext", "DOM", "es5", "es6", "dom.iterable", "es2022"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"jsxImportSource": "vue",
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"rootDir": "./",
|
"rootDir": "./",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
@ -5,7 +5,7 @@ import pkg from './package.json'
|
|||||||
import vitePlugins from './vite.plugin.config'
|
import vitePlugins from './vite.plugin.config'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(async ({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const { dependencies, devDependencies, name, version } = pkg
|
const { dependencies, devDependencies, name, version } = pkg
|
||||||
const {
|
const {
|
||||||
server,
|
server,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user