mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-03 13:44:47 +08:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90a61a1000 | ||
|
|
ad34c7b891 | ||
|
|
c5b107eab9 | ||
|
|
a8c59c5c36 | ||
|
|
0d4d3a301b | ||
|
|
b10c3eb1bb | ||
|
|
9b62d6ef1e | ||
|
|
8ff242ea45 | ||
|
|
867ef87a34 | ||
|
|
2235d9d7a8 | ||
|
|
5c82fdcd0f | ||
|
|
641355083c | ||
|
|
cadd611559 | ||
|
|
fb734f3394 | ||
|
|
e4a87e2138 | ||
|
|
12db42892d | ||
|
|
13a0db0180 | ||
|
|
facb09d779 | ||
|
|
617f8e936c | ||
|
|
6e48ad79a7 | ||
|
|
3984ab19c9 | ||
|
|
49a9259f2e | ||
|
|
867bbad1be | ||
|
|
ead4318163 | ||
|
|
bfa9203883 | ||
|
|
4f5f18f61c | ||
|
|
df71c7f75c | ||
|
|
c4839aa5f4 | ||
|
|
c19fbb1473 | ||
|
|
3cdebf4ee9 | ||
|
|
2bb433c3cd | ||
|
|
731e9b2f57 | ||
|
|
b606fa454d | ||
|
|
c6bd3f11b6 | ||
|
|
d11398274a | ||
|
|
b2081b3481 | ||
|
|
f5b7ee5a81 | ||
|
|
20a1293a55 |
@@ -1,14 +1,8 @@
|
||||
# 项目本地运行端口号
|
||||
# 平台本地运行端口号
|
||||
VITE_PORT = 8848
|
||||
|
||||
# 开发环境读取配置文件路径
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 开发环境代理
|
||||
VITE_PROXY_DOMAIN = /api
|
||||
|
||||
# 开发环境路由历史模式
|
||||
# 开发环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
# 开发环境后端地址
|
||||
VITE_PROXY_DOMAIN_REAL = "http://127.0.0.1:3000"
|
||||
@@ -1,15 +1,9 @@
|
||||
# 线上环境项目打包路径
|
||||
# 线上环境平台打包路径
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 线上环境路由历史模式
|
||||
# 线上环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
# 线上环境后端地址
|
||||
VITE_PROXY_DOMAIN_REAL = ""
|
||||
|
||||
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
|
||||
VITE_LEGACY = false
|
||||
|
||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||
VITE_CDN = false
|
||||
|
||||
|
||||
12
.env.staging
12
.env.staging
@@ -4,19 +4,13 @@ NODE_ENV=production
|
||||
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 线上环境路由历史模式
|
||||
# 预发布环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
# 线上环境后端地址
|
||||
VITE_PROXY_DOMAIN_REAL = ""
|
||||
|
||||
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
|
||||
VITE_LEGACY = false
|
||||
|
||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||
VITE_CDN = false
|
||||
VITE_CDN = true
|
||||
|
||||
# 是否启用gzip压缩或brotli压缩(分两种情况,删除原始文件和不删除原始文件)
|
||||
# 压缩时不删除原始文件的配置:gzip、brotli、both(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
|
||||
# 压缩时删除原始文件的配置:gzip-clear、brotli-clear、both-clear(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
|
||||
VITE_COMPRESSION = "none"
|
||||
VITE_COMPRESSION = "both-clear"
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
public
|
||||
dist
|
||||
*.d.ts
|
||||
/src/assets
|
||||
package.json
|
||||
.eslintrc.js
|
||||
.prettierrc.js
|
||||
commitlint.config.js
|
||||
postcss.config.js
|
||||
tailwind.config.js
|
||||
stylelint.config.js
|
||||
stylelint.config.js
|
||||
src/components/ReSplitPane/iconfont
|
||||
src/components/ReFlowChart/src/assets/iconfont
|
||||
@@ -1,3 +1,48 @@
|
||||
# 3.7.1 (2022-11-22)
|
||||
|
||||
### 🔥 hotfix
|
||||
|
||||
- Fixed the problem that the tab page may not be reset when logging out when the tab page cache is not turned on
|
||||
|
||||
# 3.7.0 (2022-11-21)
|
||||
|
||||
### ✔️ refactor
|
||||
|
||||
- Replace `driver.js` with `intro.js`
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- Add front-end single sign-on, test address https://yiming_chang.gitee.io/vue-pure-admin/#/pure-table/index?username=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
|
||||
- Add more examples for [@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table) and `element-plus` [table](https://element-plus.org /zh-CN/component/table.html) example remains the same
|
||||
- Rich watermark function page (supports customizing various colors, shadows, text, additional attributes, setting undeletable watermarks and setting watermarks for specified elements)
|
||||
- Optimize the menu, add `MenuArrowIconNoTransition` global configuration, configure it in `public/serverConfig.json`, for the left menu mode, the menu expansion can be set `MenuArrowIconNoTransition: true` to solve
|
||||
- Replacement form designer component demo
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Repair the in-page menu with parameters to jump to each other, the label is not selected and highlighted
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- Removed deprecated `$baseUrl`
|
||||
- Compatible importing a certain library leads to `global is not defined` error, importing `src/utils/globalPolyfills.ts` file into `src/main.ts` can solve the problem
|
||||
- Remove `@vitejs/plugin-legacy`, `vue3` cannot make it support `ie` through any tool
|
||||
|
||||
# 3.6.4 (2022-11-10)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- Menu icon `icon` supports using online icons
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Fixed `vxe-button` font color issue after mouse overlay and some other style issues
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- Optimize the routing guard, if you have logged in and there is login information, you cannot jump to the routing whitelist, but continue to stay on the current page
|
||||
- Removed `baseURL` and global environment proxy, and can be written directly in `vite.config.ts`, which is convenient and supports multiple proxy addresses
|
||||
|
||||
# 3.6.3 (2022-11-01)
|
||||
|
||||
### 🎫 Feat
|
||||
@@ -106,7 +151,7 @@
|
||||
|
||||
- Secondary encapsulation of `Table` of `element-plus` into [@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table), providing flexible configuration items and integrating into the platform
|
||||
- Secondary encapsulation of `Descriptions` of `element-plus` into [@pureadmin/descriptions](https://github.com/xiaoxian521/pure-admin-descriptions), providing flexible configuration items and integrating into the platform
|
||||
- Centralize most of the tools and hooks of the platform to [@pureadmin/utils](https://pure-admin-utils-docs.vercel.app/), and delete the code concentrated in this library to reduce the size of the platform
|
||||
- Centralize most of the tools and hooks of the platform to [@pureadmin/utils](https://pure-admin-utils.netlify.app), and delete the code concentrated in this library to reduce the size of the platform
|
||||
- Add [unplugin-vue-define-options](https://www.npmjs.com/package/unplugin-vue-define-options) plugin, the page can directly write `defineOptions({name: custom name})`
|
||||
- Add project files, language analysis tool [cloc](https://www.npmjs.com/package/cloc)
|
||||
- Added landing page internationalization
|
||||
@@ -267,7 +312,6 @@
|
||||
- Optimize the tab page to bring a better interactive experience
|
||||
- Routing title supports direct writing in Chinese, which can be separated from internationalization
|
||||
- Route history mode is read from env and supports base parameter
|
||||
- Packaged files provide traditional browser compatibility support, configure VITE_LEGACY to true
|
||||
|
||||
# 2.6.0(2021-11-10)
|
||||
|
||||
|
||||
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,3 +1,48 @@
|
||||
# 3.7.1 (2022-11-22)
|
||||
|
||||
### 🔥 hotfix
|
||||
|
||||
- Fixed the problem that the tab page may not be reset when logging out when the tab page cache is not turned on
|
||||
|
||||
# 3.7.0 (2022-11-21)
|
||||
|
||||
### ✔️ refactor
|
||||
|
||||
- Replace `driver.js` with `intro.js`
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- Add front-end single sign-on, test address https://yiming_chang.gitee.io/vue-pure-admin/#/pure-table/index?username=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
|
||||
- Add more examples for [@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table) and `element-plus` [table](https://element-plus.org /zh-CN/component/table.html) example remains the same
|
||||
- Rich watermark function page (supports customizing various colors, shadows, text, additional attributes, setting undeletable watermarks and setting watermarks for specified elements)
|
||||
- Optimize the menu, add `MenuArrowIconNoTransition` global configuration, configure it in `public/serverConfig.json`, for the left menu mode, the menu expansion can be set `MenuArrowIconNoTransition: true` to solve
|
||||
- Replacement form designer component demo
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Repair the in-page menu with parameters to jump to each other, the label is not selected and highlighted
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- Removed deprecated `$baseUrl`
|
||||
- Compatible importing a certain library leads to `global is not defined` error, importing `src/utils/globalPolyfills.ts` file into `src/main.ts` can solve the problem
|
||||
- Remove `@vitejs/plugin-legacy`, `vue3` cannot make it support `ie` through any tool
|
||||
|
||||
# 3.6.4 (2022-11-10)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- Menu icon `icon` supports using online icons
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Fixed `vxe-button` font color issue after mouse overlay and some other style issues
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- Optimize the routing guard, if you have logged in and there is login information, you cannot jump to the routing whitelist, but continue to stay on the current page
|
||||
- Removed `baseURL` and global environment proxy, and can be written directly in `vite.config.ts`, which is convenient and supports multiple proxy addresses
|
||||
|
||||
# 3.6.3 (2022-11-01)
|
||||
|
||||
### 🎫 Feat
|
||||
@@ -106,7 +151,7 @@
|
||||
|
||||
- Secondary encapsulation of `Table` of `element-plus` into [@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table), providing flexible configuration items and integrating into the platform
|
||||
- Secondary encapsulation of `Descriptions` of `element-plus` into [@pureadmin/descriptions](https://github.com/xiaoxian521/pure-admin-descriptions), providing flexible configuration items and integrating into the platform
|
||||
- Centralize most of the tools and hooks of the platform to [@pureadmin/utils](https://pure-admin-utils-docs.vercel.app/), and delete the code concentrated in this library to reduce the size of the platform
|
||||
- Centralize most of the tools and hooks of the platform to [@pureadmin/utils](https://pure-admin-utils.netlify.app), and delete the code concentrated in this library to reduce the size of the platform
|
||||
- Add [unplugin-vue-define-options](https://www.npmjs.com/package/unplugin-vue-define-options) plugin, the page can directly write `defineOptions({name: custom name})`
|
||||
- Add project files, language analysis tool [cloc](https://www.npmjs.com/package/cloc)
|
||||
- Added landing page internationalization
|
||||
@@ -267,7 +312,6 @@
|
||||
- Optimize the tab page to bring a better interactive experience
|
||||
- Routing title supports direct writing in Chinese, which can be separated from internationalization
|
||||
- Route history mode is read from env and supports base parameter
|
||||
- Packaged files provide traditional browser compatibility support, configure VITE_LEGACY to true
|
||||
|
||||
# 2.6.0(2021-11-10)
|
||||
|
||||
|
||||
@@ -1,3 +1,48 @@
|
||||
# 3.7.1 (2022-11-22)
|
||||
|
||||
### 🔥 hotfix
|
||||
|
||||
- 修复在未开启标签页缓存时退出登录,可能存在标签页未重置的问题
|
||||
|
||||
# 3.7.0 (2022-11-21)
|
||||
|
||||
### ✔️ refactor
|
||||
|
||||
- 使用 `intro.js` 替换 `driver.js`
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- 添加前端单点登录,测试地址 https://yiming_chang.gitee.io/vue-pure-admin/#/pure-table/index?username=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
|
||||
- 为 [@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table) 添加更多的示例和 `element-plus` 的 [table](https://element-plus.org/zh-CN/component/table.html) 示例保持一致
|
||||
- 丰富水印功能页面(支持自定义各种颜色、阴影、文字、额外属性、设置不可删除水印以及给指定元素设置水印)
|
||||
- 优化菜单,添加 `MenuArrowIconNoTransition` 全局配置,在 `public/serverConfig.json` 中配置即可,对于出现左侧菜单模式,菜单展开卡顿的可设置 `MenuArrowIconNoTransition: true` 即可解决
|
||||
- 更换表单设计器组件演示
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- 修复页内菜单带参互相跳转,标签没有选中高亮
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- 删除已废弃的 `$baseUrl`
|
||||
- 兼容引入某个库导致 `global is not defined` 报错,将 `src/utils/globalPolyfills.ts` 文件引入 `src/main.ts` 即可解决
|
||||
- 删除 `@vitejs/plugin-legacy`,`vue3` 无法通过任何工具使其支持 `ie`
|
||||
|
||||
# 3.6.4 (2022-11-10)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- 菜单图标 `icon` 支持使用在线图标
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- 修复 `vxe-button` 鼠标覆盖后字体颜色问题以及一些别的样式问题
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- 优化路由守卫,如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面
|
||||
- 将 `baseURL` 和全局环境代理删除,可直接在 `vite.config.ts` 编写,即方便又支持多个代理地址
|
||||
|
||||
# 3.6.3 (2022-11-01)
|
||||
|
||||
### 🎫 Feat
|
||||
@@ -68,7 +113,7 @@
|
||||
|
||||
### ✔️ refactor
|
||||
|
||||
- 使用 `tailwindcss` 替换 `unocss`,新增 `tailwindcss` [使用文档](http://yiming_chang.gitee.io/pure-admin-doc/pages/39156f/)
|
||||
- 使用 `tailwindcss` 替换 `unocss`,新增 `tailwindcss` [使用文档](https://yiming_chang.gitee.io/pure-admin-doc/pages/tailwindcss/)
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
@@ -106,7 +151,7 @@
|
||||
|
||||
- 将 `element-plus` 的 `Table` 二次封装到[@pureadmin/table](https://github.com/xiaoxian521/pure-admin-table),提供灵活的配置项并集成到平台里
|
||||
- 将 `element-plus` 的 `Descriptions` 二次封装到[@pureadmin/descriptions](https://github.com/xiaoxian521/pure-admin-descriptions),提供灵活的配置项并集成到平台里
|
||||
- 将平台的大部分工具以及 hooks 都集中到[@pureadmin/utils](https://pure-admin-utils-docs.vercel.app/),并删除集中到这个库里的代码,减少平台体积
|
||||
- 将平台的大部分工具以及 `hooks` 都集中到[@pureadmin/utils](https://pure-admin-utils.netlify.app),并删除集中到这个库里的代码,减少平台体积
|
||||
- 添加[unplugin-vue-define-options](https://www.npmjs.com/package/unplugin-vue-define-options)插件,页面可直接写 `defineOptions({name: 自定义名称})`
|
||||
- 添加项目文件、语言分析工具 [cloc](https://www.npmjs.com/package/cloc)
|
||||
- 添加登录页国际化
|
||||
@@ -267,7 +312,6 @@
|
||||
- 优化标签页,带来更好的交互体验
|
||||
- 路由 title 支持直接写中文,可脱离国际化
|
||||
- 路由历史模式从 env 读取并支持 base 参数
|
||||
- 打包后的文件提供传统浏览器兼容性支持,配置 VITE_LEGACY 为 true
|
||||
|
||||
# 2.6.0(2021-11-10)
|
||||
|
||||
|
||||
@@ -8,18 +8,17 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
vue-pure-admin is a free and open source middle and back-end template. Using the latest `vue3` `vite2` `Element-Plus` `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference.
|
||||
`vue-pure-admin` is an open source free and out-of-the-box middle and background management system template. Developed using the latest mainstream technologies such as `Vue3`, `Vite`, `Element-Plus`, `TypeScript`, `Pinia`, `Tailwindcss`
|
||||
|
||||
## Supporting Video
|
||||
|
||||
- [Click Watch Tutorial](https://www.bilibili.com/video/BV1534y1S7HV)
|
||||
- [Click Watch Tutorial](https://www.bilibili.com/video/BV1kg411v7QT)
|
||||
- [Click Watch UI Design](https://www.bilibili.com/video/BV17g411T7rq)
|
||||
|
||||
## Docs
|
||||
## Docs (support `PWA` fast, offline access)
|
||||
|
||||
- [Click me to view the domestic documentation site](http://yiming_chang.gitee.io/pure-admin-doc)
|
||||
- [Click me to view foreign document site 1](https://xiaoxian521.github.io/pure-admin-doc)
|
||||
- [Click me to view foreign document site 2](https://pure-admin-doc.vercel.app)
|
||||
- [Click me to view the domestic documentation site](https://yiming_chang.gitee.io/pure-admin-doc)
|
||||
- [Click me to view foreign document site](https://xiaoxian521.github.io/pure-admin-doc)
|
||||
|
||||
## Thin version (offering non-internationalized and internationalized versions)
|
||||
|
||||
@@ -30,11 +29,14 @@ vue-pure-admin is a free and open source middle and back-end template. Using the
|
||||
|
||||
- [Click Watch Tauri](https://github.com/xiaoxian521/tauri-pure-admin)
|
||||
|
||||
## Electron
|
||||
|
||||
- [Click Watch Electron](https://github.com/xiaoxian521/electron-pure-admin)
|
||||
|
||||
## Preview
|
||||
|
||||
- [Click me to view the domestic preview station](http://yiming_chang.gitee.io/vue-pure-admin)
|
||||
- [Click me to view foreign preview site 1](https://xiaoxian521.github.io/vue-pure-admin)
|
||||
- [Click me to view foreign preview station 2](https://vue-pure-admin.vercel.app)
|
||||
- [Click me to view the domestic preview station](https://yiming_chang.gitee.io/vue-pure-admin)
|
||||
- [Click me to view foreign preview site](https://xiaoxian521.github.io/vue-pure-admin)
|
||||
|
||||
- PC
|
||||
<p align="center">
|
||||
|
||||
22
README.md
22
README.md
@@ -8,18 +8,17 @@
|
||||
|
||||
## 简介
|
||||
|
||||
vue-pure-admin 是一个免费开源的中后台模版。使用了最新的`vue3` `vite2` `Element-Plus` `TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,也可用于学习参考。
|
||||
`vue-pure-admin` 是一款开源免费且开箱即用的中后台管理系统模版。使用了最新的 `Vue3`、`Vite`、`Element-Plus`、`TypeScript`、`Pinia`、`Tailwindcss` 等主流技术开发
|
||||
|
||||
## 配套视频
|
||||
|
||||
- [点我查看教程](https://www.bilibili.com/video/BV1534y1S7HV)
|
||||
- [点我查看快速开发教程](https://www.bilibili.com/video/BV1kg411v7QT)
|
||||
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
|
||||
|
||||
## 配套文档
|
||||
## 配套文档(支持 `PWA` 快速、离线访问)
|
||||
|
||||
- [点我查看国内文档站](http://yiming_chang.gitee.io/pure-admin-doc)
|
||||
- [点我查看国外文档站 1](https://xiaoxian521.github.io/pure-admin-doc)
|
||||
- [点我查看国外文档站 2](https://pure-admin-doc.vercel.app)
|
||||
- [点我查看国内文档站](https://yiming_chang.gitee.io/pure-admin-doc)
|
||||
- [点我查看国外文档站](https://xiaoxian521.github.io/pure-admin-doc)
|
||||
|
||||
## 精简版(提供非国际化、国际化两个版本选择)
|
||||
|
||||
@@ -30,11 +29,14 @@ vue-pure-admin 是一个免费开源的中后台模版。使用了最新的`vue3
|
||||
|
||||
- [点我查看 Tauri 版](https://github.com/xiaoxian521/tauri-pure-admin)
|
||||
|
||||
## Electron 版
|
||||
|
||||
- [点我查看 Electron 版](https://github.com/xiaoxian521/electron-pure-admin)
|
||||
|
||||
## 预览
|
||||
|
||||
- [点我查看国内预览站](http://yiming_chang.gitee.io/vue-pure-admin)
|
||||
- [点我查看国外预览站 1](https://xiaoxian521.github.io/vue-pure-admin)
|
||||
- [点我查看国外预览站 2](https://vue-pure-admin.vercel.app)
|
||||
- [点我查看国内预览站](https://yiming_chang.gitee.io/vue-pure-admin)
|
||||
- [点我查看国外预览站](https://xiaoxian521.github.io/vue-pure-admin)
|
||||
|
||||
- PC 端
|
||||
<p align="center">
|
||||
@@ -146,7 +148,7 @@ pnpm build
|
||||
|
||||
一群已满,下面是二群,群里严禁`黄`、`赌`、`毒`、`vpn`等违法行为!
|
||||
|
||||
<img src="http://yiming_chang.gitee.io/pure-admin-doc/img/support/qq.png" width="150px" height="225px" />
|
||||
<img src="https://yiming_chang.gitee.io/pure-admin-doc/img/support/qq.png" width="150px" height="225px" />
|
||||
|
||||
## 许可证
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
/** 处理环境变量 */
|
||||
const warpperEnv = (envConf: Recordable): ViteEnv => {
|
||||
/** 此处为默认值,无需修改 */
|
||||
/** 此处为默认值 */
|
||||
const ret: ViteEnv = {
|
||||
VITE_PORT: 8848,
|
||||
VITE_PUBLIC_PATH: "",
|
||||
VITE_PROXY_DOMAIN: "",
|
||||
VITE_PROXY_DOMAIN_REAL: "",
|
||||
VITE_ROUTER_HISTORY: "",
|
||||
VITE_LEGACY: false,
|
||||
VITE_CDN: false,
|
||||
VITE_COMPRESSION: "none"
|
||||
};
|
||||
@@ -30,14 +27,9 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
|
||||
return ret;
|
||||
};
|
||||
|
||||
/** 跨域代理重写 */
|
||||
const regExps = (value: string, reg: string): string => {
|
||||
return value.replace(new RegExp(`^${reg}`, "g"), "");
|
||||
};
|
||||
|
||||
/** 环境变量 */
|
||||
/** 获取环境变量 */
|
||||
const loadEnv = (): ViteEnv => {
|
||||
return import.meta.env;
|
||||
};
|
||||
|
||||
export { warpperEnv, regExps, loadEnv };
|
||||
export { warpperEnv, loadEnv };
|
||||
|
||||
@@ -3,20 +3,18 @@ import { resolve } from "path";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import { viteBuildInfo } from "./info";
|
||||
import svgLoader from "vite-svg-loader";
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import VueMacros from "unplugin-vue-macros/vite";
|
||||
import { viteMockServe } from "vite-plugin-mock";
|
||||
import { configCompressPlugin } from "./compress";
|
||||
import VueI18n from "@intlify/vite-plugin-vue-i18n";
|
||||
import { visualizer } from "rollup-plugin-visualizer";
|
||||
import removeConsole from "vite-plugin-remove-console";
|
||||
import themePreprocessorPlugin from "@pureadmin/theme";
|
||||
import DefineOptions from "unplugin-vue-define-options/vite";
|
||||
import { genScssMultipleScopeVars } from "../src/layout/theme";
|
||||
|
||||
export function getPluginsList(
|
||||
command: string,
|
||||
VITE_LEGACY: boolean,
|
||||
VITE_CDN: boolean,
|
||||
VITE_COMPRESSION: ViteCompression
|
||||
) {
|
||||
@@ -34,7 +32,7 @@ export function getPluginsList(
|
||||
vueJsx(),
|
||||
VITE_CDN ? cdn : null,
|
||||
configCompressPlugin(VITE_COMPRESSION),
|
||||
DefineOptions(),
|
||||
VueMacros(),
|
||||
// 线上环境删除console
|
||||
removeConsole({ external: ["src/assets/iconfont/iconfont.js"] }),
|
||||
viteBuildInfo(),
|
||||
@@ -65,13 +63,6 @@ export function getPluginsList(
|
||||
`,
|
||||
logger: false
|
||||
}),
|
||||
// 是否为打包后的文件提供传统浏览器兼容性支持
|
||||
VITE_LEGACY
|
||||
? legacy({
|
||||
targets: ["ie >= 11"],
|
||||
additionalLegacyPolyfills: ["regenerator-runtime/runtime"]
|
||||
})
|
||||
: null,
|
||||
// 打包分析
|
||||
lifecycle === "report"
|
||||
? visualizer({ open: true, brotliSize: true, filename: "report.html" })
|
||||
|
||||
@@ -89,7 +89,7 @@ const frameRouter = {
|
||||
meta: {
|
||||
icon: "monitor",
|
||||
title: "menus.hsExternalPage",
|
||||
rank: 7
|
||||
rank: 8
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@@ -97,13 +97,13 @@ const frameRouter = {
|
||||
name: "FramePure",
|
||||
meta: {
|
||||
title: "menus.hsPureDocument",
|
||||
frameSrc: "http://yiming_chang.gitee.io/pure-admin-doc",
|
||||
frameSrc: "https://yiming_chang.gitee.io/pure-admin-doc",
|
||||
roles: ["admin", "common"]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/external",
|
||||
name: "http://yiming_chang.gitee.io/pure-admin-doc",
|
||||
name: "https://yiming_chang.gitee.io/pure-admin-doc",
|
||||
meta: {
|
||||
title: "menus.externalLink",
|
||||
roles: ["admin", "common"]
|
||||
@@ -137,6 +137,7 @@ const tabsRouter = {
|
||||
roles: ["admin", "common"]
|
||||
}
|
||||
},
|
||||
// query 传参模式
|
||||
{
|
||||
path: "/tabs/query-detail",
|
||||
name: "TabQueryDetail",
|
||||
@@ -146,11 +147,13 @@ const tabsRouter = {
|
||||
roles: ["admin", "common"]
|
||||
}
|
||||
},
|
||||
// params 传参模式
|
||||
{
|
||||
path: "/tabs/params-detail/:id",
|
||||
component: "params-detail",
|
||||
name: "TabParamsDetail",
|
||||
meta: {
|
||||
// 不在menu菜单中显示
|
||||
showLink: false,
|
||||
roles: ["admin", "common"]
|
||||
}
|
||||
|
||||
80
package.json
80
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-pure-admin",
|
||||
"version": "3.6.3",
|
||||
"version": "3.7.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "NODE_OPTIONS=--max-old-space-size=4096 vite",
|
||||
@@ -30,15 +30,14 @@
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@ctrl/tinycolor": "^3.4.1",
|
||||
"@logicflow/core": "^1.1.24",
|
||||
"@logicflow/extension": "^1.1.24",
|
||||
"@logicflow/core": "^1.1.30",
|
||||
"@logicflow/extension": "^1.1.30",
|
||||
"@pureadmin/components": "^1.1.0",
|
||||
"@pureadmin/descriptions": "^1.1.0",
|
||||
"@pureadmin/table": "^1.2.0",
|
||||
"@pureadmin/utils": "^1.1.5",
|
||||
"@vueuse/core": "^9.4.0",
|
||||
"@vueuse/motion": "^2.0.0-beta.12",
|
||||
"@vueuse/shared": "^9.4.0",
|
||||
"@pureadmin/table": "^1.6.0",
|
||||
"@pureadmin/utils": "^1.6.7",
|
||||
"@vueuse/core": "^9.5.0",
|
||||
"@vueuse/motion": "2.0.0-beta.12",
|
||||
"@wangeditor/editor": "^5.1.21",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"animate.css": "^4.1.1",
|
||||
@@ -46,11 +45,11 @@
|
||||
"china-area-data": "^5.0.1",
|
||||
"cropperjs": "^1.5.12",
|
||||
"dayjs": "^1.11.5",
|
||||
"driver.js": "^0.9.8",
|
||||
"echarts": "^5.4.0",
|
||||
"el-table-infinite-scroll": "^3.0.1",
|
||||
"element-plus": "^2.2.18",
|
||||
"element-resize-detector": "^1.2.3",
|
||||
"element-plus": "^2.2.22",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"intro.js": "^6.0.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"jsbarcode": "^3.11.5",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -60,7 +59,7 @@
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path": "^0.12.7",
|
||||
"pinia": "^2.0.23",
|
||||
"pinia": "^2.0.24",
|
||||
"qrcode": "^1.5.1",
|
||||
"qs": "^6.11.0",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
@@ -69,8 +68,7 @@
|
||||
"swiper": "^8.4.4",
|
||||
"typeit": "^8.7.0",
|
||||
"v-contextmenu": "3.0.0",
|
||||
"vue": "^3.2.40",
|
||||
"vue-form-create2": "^1.2.8",
|
||||
"vue": "^3.2.45",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-json-pretty": "^2.2.2",
|
||||
"vue-pdf-embed": "^1.1.4",
|
||||
@@ -96,65 +94,65 @@
|
||||
"@iconify-icons/mdi": "^1.2.8",
|
||||
"@iconify-icons/ri": "^1.2.3",
|
||||
"@iconify-icons/uil": "^1.2.2",
|
||||
"@iconify/vue": "^3.2.1",
|
||||
"@iconify/vue": "^4.0.0",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||
"@pureadmin/theme": "^2.4.0",
|
||||
"@types/element-resize-detector": "1.1.3",
|
||||
"@types/intro.js": "^5.1.0",
|
||||
"@types/js-cookie": "^3.0.1",
|
||||
"@types/lodash": "^4.14.180",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mockjs": "1.0.3",
|
||||
"@types/node": "14.14.14",
|
||||
"@types/mockjs": "^1.0.7",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/sortablejs": "^1.13.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^5.10.2",
|
||||
"@vitejs/plugin-legacy": "^2.2.0",
|
||||
"@vitejs/plugin-vue": "^3.1.2",
|
||||
"@vitejs/plugin-vue-jsx": "^2.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
||||
"@typescript-eslint/parser": "^5.43.0",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.1",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"@vue/runtime-core": "^3.2.40",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/runtime-core": "^3.2.45",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"cloc": "^2.10.0",
|
||||
"cssnano": "^5.1.13",
|
||||
"cssnano": "^5.1.14",
|
||||
"eslint": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.4.1",
|
||||
"eslint-plugin-vue": "^9.7.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"husky": "^7.0.4",
|
||||
"lint-staged": "11.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.17",
|
||||
"postcss": "^8.4.18",
|
||||
"postcss-html": "^1.5.0",
|
||||
"postcss-import": "^15.0.0",
|
||||
"postcss-scss": "^4.0.5",
|
||||
"prettier": "^2.5.1",
|
||||
"pretty-quick": "3.1.1",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup-plugin-visualizer": "^5.8.2",
|
||||
"sass": "^1.53.0",
|
||||
"sass-loader": "^13.0.2",
|
||||
"rollup-plugin-visualizer": "^5.8.3",
|
||||
"sass": "^1.56.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"stylelint": "^14.3.0",
|
||||
"stylelint-config-html": "^1.0.0",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^6.0.0",
|
||||
"stylelint-config-standard": "^24.0.0",
|
||||
"stylelint-config-recommended": "^9.0.0",
|
||||
"stylelint-config-standard": "^29.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"terser": "^5.15.0",
|
||||
"typescript": "^4.7.4",
|
||||
"unplugin-vue-define-options": "0.7.3",
|
||||
"vite": "^3.1.8",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"terser": "^5.15.1",
|
||||
"typescript": "^4.9.3",
|
||||
"unplugin-vue-macros": "^0.16.3",
|
||||
"vite": "3.1.8",
|
||||
"vite-plugin-cdn-import": "^0.3.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-remove-console": "^1.1.0",
|
||||
"vite-plugin-remove-console": "^1.3.0",
|
||||
"vite-svg-loader": "^3.6.0",
|
||||
"vue-eslint-parser": "^8.2.0",
|
||||
"vue-tsc": "^0.40.13"
|
||||
"vue-eslint-parser": "^9.1.0",
|
||||
"vue-tsc": "^1.0.9"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
|
||||
2492
pnpm-lock.yaml
generated
2492
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"Version": "3.6.3",
|
||||
"Version": "3.7.1",
|
||||
"Title": "PureAdmin",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
@@ -16,6 +16,7 @@
|
||||
"EpThemeColor": "#409EFF",
|
||||
"ShowLogo": true,
|
||||
"ShowModel": "smart",
|
||||
"MenuArrowIconNoTransition": false,
|
||||
"MapConfigure": {
|
||||
"amapKey": "97b3248d1553172e81f168cf94ea667e",
|
||||
"options": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { http } from "../utils/http";
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
type Result = {
|
||||
success: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { http } from "../utils/http";
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
type Result = {
|
||||
success: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { http } from "../utils/http";
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
type Result = {
|
||||
success: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { http } from "../utils/http";
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
type Result = {
|
||||
success: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { http } from "../utils/http";
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
export type UserResult = {
|
||||
success: boolean;
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
computed,
|
||||
PropType
|
||||
} from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { useAttrs } from "@pureadmin/utils";
|
||||
|
||||
import Cropper from "cropperjs";
|
||||
@@ -78,7 +77,7 @@ export default defineComponent({
|
||||
props,
|
||||
setup(props) {
|
||||
const cropper: any = ref<Nullable<Cropper>>(null);
|
||||
const imgElRef = templateRef<HTMLImageElement | null>("imgElRef", null);
|
||||
const imgElRef = ref();
|
||||
|
||||
const isReady = ref<boolean>(false);
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, unref, nextTick, onUnmounted } from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import flippers from "./filpper";
|
||||
|
||||
let timer = ref(null);
|
||||
let flipObjs = ref([]);
|
||||
const timer = ref(null);
|
||||
const flipObjs = ref([]);
|
||||
|
||||
const flipperHour1 = templateRef<HTMLElement | null>("flipperHour1", null);
|
||||
const flipperHour2 = templateRef<HTMLElement | null>("flipperHour2", null);
|
||||
const flipperMinute1 = templateRef<HTMLElement | null>("flipperMinute1", null);
|
||||
const flipperMinute2 = templateRef<HTMLElement | null>("flipperMinute2", null);
|
||||
const flipperSecond1 = templateRef<HTMLElement | null>("flipperSecond1", null);
|
||||
const flipperSecond2 = templateRef<HTMLElement | null>("flipperSecond2", null);
|
||||
const flipperHour1 = ref();
|
||||
const flipperHour2 = ref();
|
||||
const flipperMinute1 = ref();
|
||||
const flipperMinute2 = ref();
|
||||
const flipperSecond1 = ref();
|
||||
const flipperSecond2 = ref();
|
||||
|
||||
// 初始化数字
|
||||
const init = () => {
|
||||
let now = new Date();
|
||||
let nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss");
|
||||
const now = new Date();
|
||||
const nowTimeStr = formatDate(new Date(now.getTime()), "hhiiss");
|
||||
for (let i = 0; i < flipObjs.value.length; i++) {
|
||||
flipObjs?.value[i]?.setFront(nowTimeStr[i]);
|
||||
}
|
||||
@@ -26,9 +25,9 @@ const init = () => {
|
||||
const run = () => {
|
||||
timer.value = setInterval(() => {
|
||||
// 获取当前时间
|
||||
let now = new Date();
|
||||
let nowTimeStr = formatDate(new Date(now.getTime() - 1000), "hhiiss");
|
||||
let nextTimeStr = formatDate(now, "hhiiss");
|
||||
const now = new Date();
|
||||
const nowTimeStr = formatDate(new Date(now.getTime() - 1000), "hhiiss");
|
||||
const nextTimeStr = formatDate(now, "hhiiss");
|
||||
for (let i = 0; i < flipObjs.value.length; i++) {
|
||||
if (nowTimeStr[i] === nextTimeStr[i]) {
|
||||
continue;
|
||||
@@ -52,17 +51,17 @@ const formatDate = (date: Date, dateFormat: string) => {
|
||||
);
|
||||
}
|
||||
// 格式化月、日、时、分、秒
|
||||
let o = {
|
||||
const o = {
|
||||
"m+": date.getMonth() + 1,
|
||||
"d+": date.getDate(),
|
||||
"h+": date.getHours(),
|
||||
"i+": date.getMinutes(),
|
||||
"s+": date.getSeconds()
|
||||
};
|
||||
for (let k in o) {
|
||||
for (const k in o) {
|
||||
if (new RegExp(`(${k})`).test(dateFormat)) {
|
||||
// 取出对应的值
|
||||
let str = o[k] + "";
|
||||
const str = o[k] + "";
|
||||
/* 根据设置的格式,输出对应的字符
|
||||
* 例如: 早上8时,hh => 08,h => 8
|
||||
* 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, unref, onMounted } from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { LogicFlow } from "@logicflow/core";
|
||||
|
||||
interface Props {
|
||||
@@ -16,11 +15,11 @@ const emit = defineEmits<{
|
||||
(e: "catData"): void;
|
||||
}>();
|
||||
|
||||
const controlButton3 = templateRef<HTMLElement | any>("controlButton3", null);
|
||||
const controlButton4 = templateRef<HTMLElement | any>("controlButton4", null);
|
||||
const controlButton3 = ref();
|
||||
const controlButton4 = ref();
|
||||
|
||||
let focusIndex = ref<Number>(-1);
|
||||
let titleLists = ref([
|
||||
const focusIndex = ref<Number>(-1);
|
||||
const titleLists = ref([
|
||||
{
|
||||
icon: "icon-zoom-out-hs",
|
||||
text: "缩小",
|
||||
@@ -68,7 +67,7 @@ let titleLists = ref([
|
||||
const onControl = (item, key) => {
|
||||
["zoom", "zoom", "resetZoom", "undo", "redo", "getSnapshot"].forEach(
|
||||
(v, i) => {
|
||||
let domControl = props.lf;
|
||||
const domControl = props.lf;
|
||||
if (key === 1) {
|
||||
domControl.zoom(true);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
nodeList: null
|
||||
});
|
||||
|
||||
let properties = ref({
|
||||
const properties = ref({
|
||||
a: "efrwe",
|
||||
b: "wewe"
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import iconifyIconOnline from "./src/iconifyIconOnline";
|
||||
import iconSelect from "./src/Select.vue";
|
||||
import fontIcon from "./src/iconfont";
|
||||
|
||||
/** 离线图标组件 */
|
||||
/** 本地图标组件 */
|
||||
const IconifyIconOffline = iconifyIconOffline;
|
||||
/** 在线图标组件 */
|
||||
const IconifyIconOnline = iconifyIconOnline;
|
||||
|
||||
@@ -16,21 +16,21 @@ const props = defineProps({
|
||||
});
|
||||
const emit = defineEmits<{ (e: "update:modelValue", v: string) }>();
|
||||
|
||||
let visible = ref(false);
|
||||
let inputValue = toRef(props, "modelValue");
|
||||
let iconList = ref(IconJson);
|
||||
let icon = ref("add-location");
|
||||
let currentActiveType = ref("ep:");
|
||||
const visible = ref(false);
|
||||
const inputValue = toRef(props, "modelValue");
|
||||
const iconList = ref(IconJson);
|
||||
const icon = ref("add-location");
|
||||
const currentActiveType = ref("ep:");
|
||||
// 深拷贝图标数据,前端做搜索
|
||||
let copyIconList = cloneDeep(iconList.value);
|
||||
const copyIconList = cloneDeep(iconList.value);
|
||||
|
||||
let pageSize = ref(96);
|
||||
let currentPage = ref(1);
|
||||
const pageSize = ref(96);
|
||||
const currentPage = ref(1);
|
||||
|
||||
// 搜索条件
|
||||
let filterValue = ref("");
|
||||
const filterValue = ref("");
|
||||
|
||||
let tabsList = [
|
||||
const tabsList = [
|
||||
{
|
||||
label: "Element Plus",
|
||||
name: "ep:"
|
||||
@@ -45,7 +45,7 @@ let tabsList = [
|
||||
}
|
||||
];
|
||||
|
||||
let pageList = computed(() => {
|
||||
const pageList = computed(() => {
|
||||
if (currentPage.value === 1) {
|
||||
return copyIconList[currentActiveType.value]
|
||||
.filter(v => v.includes(filterValue.value))
|
||||
|
||||
@@ -3,7 +3,8 @@ import { h, defineComponent, Component } from "vue";
|
||||
import { IconifyIconOnline, IconifyIconOffline, FontIcon } from "../index";
|
||||
|
||||
/**
|
||||
* 支持fontawesome4、5+、iconfont、remixicon、element-plus的icons、自定义svg
|
||||
* 支持 `iconfont`、自定义 `svg` 以及 `iconify` 中所有的图标
|
||||
* @see 点击查看文档图标篇 {@link https://yiming_chang.gitee.io/pure-admin-doc/pages/icon/}
|
||||
* @param icon 必传 图标
|
||||
* @param attrs 可选 iconType 属性
|
||||
* @returns Component
|
||||
@@ -34,11 +35,12 @@ export function useRenderIcon(icon: any, attrs?: iconType): Component {
|
||||
// svg
|
||||
return icon;
|
||||
} else {
|
||||
// 通过是否存在 : 符号来判断是在线还是本地图标,存在即是在线图标,反之
|
||||
return defineComponent({
|
||||
name: "Icon",
|
||||
render() {
|
||||
const IconifyIcon =
|
||||
attrs && attrs["online"] ? IconifyIconOnline : IconifyIconOffline;
|
||||
icon && icon.includes(":") ? IconifyIconOnline : IconifyIconOffline;
|
||||
return h(IconifyIcon, {
|
||||
icon: icon,
|
||||
...attrs
|
||||
|
||||
@@ -29,6 +29,10 @@ import Refresh from "@iconify-icons/ep/refresh";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import More from "@iconify-icons/ep/more-filled";
|
||||
import EpArrowDown from "@iconify-icons/ep/arrow-down";
|
||||
import ArrowUp from "@iconify-icons/ep/arrow-up";
|
||||
import ArrowRight from "@iconify-icons/ep/arrow-right";
|
||||
import ArrowLeft from "@iconify-icons/ep/arrow-left";
|
||||
addIcon("check", Check);
|
||||
addIcon("menu", Menu);
|
||||
addIcon("home-filled", HomeFilled);
|
||||
@@ -56,6 +60,10 @@ addIcon("refresh", Refresh);
|
||||
addIcon("edits", EditPen);
|
||||
addIcon("delete", Delete);
|
||||
addIcon("more", More);
|
||||
addIcon("ep-arrow-down", EpArrowDown);
|
||||
addIcon("ep-arrow-up", ArrowUp);
|
||||
addIcon("ep-arrow-right", ArrowRight);
|
||||
addIcon("ep-arrow-left", ArrowLeft);
|
||||
|
||||
// remixicon
|
||||
import ArrowRightSLine from "@iconify-icons/ri/arrow-right-s-line";
|
||||
@@ -161,7 +169,7 @@ addIcon("unExpand", UnExpand);
|
||||
import LocationCompany from "@iconify-icons/carbon/location-company";
|
||||
addIcon("location-company", LocationCompany);
|
||||
|
||||
// Iconify Icon在Vue里离线使用(用于内网环境)https://docs.iconify.design/icon-components/vue/offline.html
|
||||
// Iconify Icon在Vue里本地使用(用于内网环境)https://docs.iconify.design/icon-components/vue/offline.html
|
||||
export default defineComponent({
|
||||
name: "IconifyIconOffline",
|
||||
components: { IconifyIcon },
|
||||
|
||||
@@ -11,7 +11,6 @@ export interface iconType {
|
||||
horizontalAlign?: boolean;
|
||||
verticalAlign?: boolean;
|
||||
align?: string;
|
||||
online?: boolean;
|
||||
onLoad?: Function;
|
||||
includes?: Function;
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ const complete = (): void => {
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!instance) return;
|
||||
let { MapConfigure } = instance.appContext.config.globalProperties.$config;
|
||||
let { options } = MapConfigure;
|
||||
const { MapConfigure } = instance.appContext.config.globalProperties.$config;
|
||||
const { options } = MapConfigure;
|
||||
|
||||
AMapLoader.load({
|
||||
key: MapConfigure.amapKey,
|
||||
@@ -67,10 +67,10 @@ onBeforeMount(() => {
|
||||
gridSize: 80,
|
||||
maxZoom: 14,
|
||||
renderMarker(ctx) {
|
||||
let { marker, data } = ctx;
|
||||
const { marker, data } = ctx;
|
||||
if (Array.isArray(data) && data[0]) {
|
||||
var { driver, plateNumber, orientation } = data[0];
|
||||
var content = `<img style="transform: scale(1) rotate(${
|
||||
const { driver, plateNumber, orientation } = data[0];
|
||||
const content = `<img style="transform: scale(1) rotate(${
|
||||
360 - Number(orientation)
|
||||
}deg);" src='${car}' />`;
|
||||
marker.setContent(content);
|
||||
@@ -93,7 +93,7 @@ onBeforeMount(() => {
|
||||
// 获取模拟车辆信息
|
||||
mapJson()
|
||||
.then(({ data }) => {
|
||||
let points: object = data.map(v => {
|
||||
const points: object = data.map(v => {
|
||||
return {
|
||||
lnglat: [v.lng, v.lat],
|
||||
...v
|
||||
|
||||
@@ -28,16 +28,16 @@ const emit = defineEmits<{
|
||||
(e: "scrollEnd"): void;
|
||||
}>();
|
||||
|
||||
let xPos = ref<number>(0);
|
||||
let yPos = ref<number>(0);
|
||||
let delay = ref<number>(0);
|
||||
let height = ref<number>(0);
|
||||
const xPos = ref<number>(0);
|
||||
const yPos = ref<number>(0);
|
||||
const delay = ref<number>(0);
|
||||
const height = ref<number>(0);
|
||||
// 外容器宽度
|
||||
let width = ref<number>(0);
|
||||
const width = ref<number>(0);
|
||||
// 内容实际宽度
|
||||
let realBoxWidth = ref<number>(0);
|
||||
let realBoxHeight = ref<number>(0);
|
||||
let copyHtml = ref("");
|
||||
const realBoxWidth = ref<number>(0);
|
||||
const realBoxHeight = ref<number>(0);
|
||||
const copyHtml = ref("");
|
||||
// single 单步滚动的定时器
|
||||
let singleWaitTime = null;
|
||||
// move动画的animationFrame定时器
|
||||
@@ -52,7 +52,7 @@ let isHover = false;
|
||||
let ease = "ease-in";
|
||||
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
let { classOption } = props;
|
||||
const { classOption } = props;
|
||||
|
||||
if (classOption["key"] === undefined) {
|
||||
classOption["key"] = 0;
|
||||
@@ -68,15 +68,15 @@ const realBox = templateRef<HTMLElement | null>(
|
||||
null
|
||||
);
|
||||
|
||||
let leftSwitchState = computed(() => {
|
||||
const leftSwitchState = computed(() => {
|
||||
return unref(xPos) < 0;
|
||||
});
|
||||
|
||||
let rightSwitchState = computed(() => {
|
||||
const rightSwitchState = computed(() => {
|
||||
return Math.abs(unref(xPos)) < unref(realBoxWidth) - unref(width);
|
||||
});
|
||||
|
||||
let defaultOption = computed(() => {
|
||||
const defaultOption = computed(() => {
|
||||
return {
|
||||
//步长
|
||||
step: 1,
|
||||
@@ -105,7 +105,7 @@ let defaultOption = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
let options = computed(() => {
|
||||
const options = computed(() => {
|
||||
// @ts-expect-error
|
||||
return copyObj({}, unref(defaultOption), classOption);
|
||||
});
|
||||
@@ -114,11 +114,11 @@ const leftSwitchClass = computed(() => {
|
||||
return unref(leftSwitchState) ? "" : unref(options).switchDisabledClass;
|
||||
});
|
||||
|
||||
let rightSwitchClass = computed(() => {
|
||||
const rightSwitchClass = computed(() => {
|
||||
return unref(rightSwitchState) ? "" : unref(options).switchDisabledClass;
|
||||
});
|
||||
|
||||
let leftSwitch = computed((): CSSProperties => {
|
||||
const leftSwitch = computed((): CSSProperties => {
|
||||
return {
|
||||
position: "absolute",
|
||||
margin: `${unref(height) / 2}px 0 0 -${unref(options).switchOffset}px`,
|
||||
@@ -126,7 +126,7 @@ let leftSwitch = computed((): CSSProperties => {
|
||||
};
|
||||
});
|
||||
|
||||
let rightSwitch = computed((): CSSProperties => {
|
||||
const rightSwitch = computed((): CSSProperties => {
|
||||
return {
|
||||
position: "absolute",
|
||||
margin: `${unref(height) / 2}px 0 0 ${
|
||||
@@ -136,19 +136,19 @@ let rightSwitch = computed((): CSSProperties => {
|
||||
};
|
||||
});
|
||||
|
||||
let isHorizontal = computed(() => {
|
||||
const isHorizontal = computed(() => {
|
||||
return (
|
||||
unref(options).direction !== "bottom" && unref(options).direction !== "top"
|
||||
);
|
||||
});
|
||||
|
||||
let float = computed((): CSSProperties => {
|
||||
const float = computed((): CSSProperties => {
|
||||
return unref(isHorizontal)
|
||||
? { float: "left", overflow: "hidden" }
|
||||
: { overflow: "hidden" };
|
||||
});
|
||||
|
||||
let pos = computed(() => {
|
||||
const pos = computed(() => {
|
||||
return {
|
||||
transform: `translate(${unref(xPos)}px,${unref(yPos)}px)`,
|
||||
transition: `all ${ease} ${unref(delay)}ms`,
|
||||
@@ -156,45 +156,45 @@ let pos = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
let navigation = computed(() => {
|
||||
const navigation = computed(() => {
|
||||
return unref(options).navigation;
|
||||
});
|
||||
|
||||
let autoPlay = computed(() => {
|
||||
const autoPlay = computed(() => {
|
||||
if (unref(navigation)) return false;
|
||||
return unref(options).autoPlay;
|
||||
});
|
||||
|
||||
let scrollSwitch = computed(() => {
|
||||
const scrollSwitch = computed(() => {
|
||||
// 从 props 解构出来的 属性 不再具有响应性.
|
||||
return (props.data as any).length >= unref(options).limitMoveNum;
|
||||
});
|
||||
|
||||
let hoverStopSwitch = computed(() => {
|
||||
const hoverStopSwitch = computed(() => {
|
||||
return unref(options).hoverStop && unref(autoPlay) && unref(scrollSwitch);
|
||||
});
|
||||
|
||||
let canTouchScroll = computed(() => {
|
||||
const canTouchScroll = computed(() => {
|
||||
return unref(options).openTouch;
|
||||
});
|
||||
|
||||
let baseFontSize = computed(() => {
|
||||
const baseFontSize = computed(() => {
|
||||
return unref(options).isSingleRemUnit
|
||||
? parseInt(window.getComputedStyle(document.documentElement, null).fontSize)
|
||||
: 1;
|
||||
});
|
||||
|
||||
let realSingleStopWidth = computed(() => {
|
||||
const realSingleStopWidth = computed(() => {
|
||||
return unref(options).singleWidth * unref(baseFontSize);
|
||||
});
|
||||
|
||||
let realSingleStopHeight = computed(() => {
|
||||
const realSingleStopHeight = computed(() => {
|
||||
return unref(options).singleHeight * unref(baseFontSize);
|
||||
});
|
||||
|
||||
let step = computed(() => {
|
||||
const step = computed(() => {
|
||||
let singleStep;
|
||||
let step = unref(options).step;
|
||||
const step = unref(options).step;
|
||||
if (unref(isHorizontal)) {
|
||||
singleStep = unref(realSingleStopWidth);
|
||||
} else {
|
||||
@@ -275,7 +275,7 @@ function touchMove(e) {
|
||||
return;
|
||||
const touch = e.targetTouches[0];
|
||||
const { direction } = unref(options);
|
||||
let endPos = {
|
||||
const endPos = {
|
||||
x: touch.pageX - startPos.x,
|
||||
y: touch.pageY - startPos.y
|
||||
};
|
||||
@@ -300,18 +300,19 @@ function touchMove(e) {
|
||||
|
||||
function touchEnd() {
|
||||
if (!unref(canTouchScroll)) return;
|
||||
let timer;
|
||||
// eslint-disable-next-line prefer-const
|
||||
let timer: any;
|
||||
const direction = unref(options).direction;
|
||||
delay.value = 50;
|
||||
if (direction === "top") {
|
||||
if (unref(yPos) > 0) yPos.value = 0;
|
||||
} else if (direction === "bottom") {
|
||||
let h = (unref(realBoxHeight) / 2) * -1;
|
||||
const h = (unref(realBoxHeight) / 2) * -1;
|
||||
if (unref(yPos) < h) yPos.value = h;
|
||||
} else if (direction === "left") {
|
||||
if (unref(xPos) > 0) xPos.value = 0;
|
||||
} else if (direction === "right") {
|
||||
let w = unref(realBoxWidth) * -1;
|
||||
const w = unref(realBoxWidth) * -1;
|
||||
if (unref(xPos) < w) xPos.value = w;
|
||||
}
|
||||
if (timer) clearTimeout(timer);
|
||||
@@ -339,7 +340,7 @@ function scrollMove() {
|
||||
const h = unref(realBoxHeight) / 2;
|
||||
//宽度
|
||||
const w = unref(realBoxWidth) / 2;
|
||||
let { direction, waitTime } = unref(options);
|
||||
const { direction, waitTime } = unref(options);
|
||||
if (direction === "top") {
|
||||
// 上
|
||||
if (Math.abs(unref(yPos)) >= h) {
|
||||
|
||||
@@ -31,7 +31,6 @@ const getConfig = (key?: string): ServerConfigs => {
|
||||
export const getServerConfig = async (app: App): Promise<undefined> => {
|
||||
app.config.globalProperties.$config = getConfig();
|
||||
return axios({
|
||||
baseURL: "",
|
||||
method: "get",
|
||||
url: `${VITE_PUBLIC_PATH}serverConfig.json`
|
||||
})
|
||||
@@ -44,8 +43,6 @@ export const getServerConfig = async (app: App): Promise<undefined> => {
|
||||
// 设置全局配置
|
||||
setConfig($config);
|
||||
}
|
||||
// 设置全局baseURL
|
||||
app.config.globalProperties.$baseUrl = $config.baseURL;
|
||||
return $config;
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
import { ref } from "vue";
|
||||
import { noticesData } from "./data";
|
||||
import NoticeList from "./noticeList.vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { Tabs, TabPane } from "@pureadmin/components";
|
||||
|
||||
const dropdownDom = templateRef<ElRef | null>("dropdownDom", null);
|
||||
const activeName = ref(noticesData[0].name);
|
||||
const dropdownDom = ref();
|
||||
const activeKey = ref(noticesData[0].key);
|
||||
|
||||
const notices = ref(noticesData);
|
||||
|
||||
let noticesNum = ref(0);
|
||||
const noticesNum = ref(0);
|
||||
notices.value.forEach(notice => {
|
||||
noticesNum.value += notice.list.length;
|
||||
});
|
||||
@@ -33,7 +33,8 @@ function tabClick() {
|
||||
<Tabs
|
||||
centered
|
||||
class="dropdown-tabs"
|
||||
v-model:activeName="activeName"
|
||||
:tabBarStyle="{ marginLeft: notices?.length > 4 ? '8px' : '0' }"
|
||||
v-model:activeKey="activeKey"
|
||||
@tabClick="tabClick"
|
||||
>
|
||||
<template v-for="item in notices" :key="item.key">
|
||||
|
||||
@@ -24,11 +24,11 @@ function hoverTitle() {
|
||||
|
||||
function hoverDescription(event, description) {
|
||||
// currentWidth 为文本在页面中所占的宽度,创建标签,加入到页面,获取currentWidth ,最后在移除
|
||||
let tempTag = document.createElement("span");
|
||||
const tempTag = document.createElement("span");
|
||||
tempTag.innerText = description;
|
||||
tempTag.className = "getDescriptionWidth";
|
||||
document.querySelector("body").appendChild(tempTag);
|
||||
let currentWidth = (
|
||||
const currentWidth = (
|
||||
document.querySelector(".getDescriptionWidth") as HTMLSpanElement
|
||||
).offsetWidth;
|
||||
document.querySelector(".getDescriptionWidth").remove();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ref } from "vue";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import { emitter } from "@/utils/mitt";
|
||||
|
||||
let show = ref<Boolean>(false);
|
||||
const show = ref<Boolean>(false);
|
||||
const target = ref(null);
|
||||
onClickOutside(target, (event: any) => {
|
||||
if (event.clientX > target.value.offsetLeft) return;
|
||||
@@ -21,7 +21,7 @@ emitter.on("openPanel", () => {
|
||||
<div ref="target" class="right-panel bg-bg_color">
|
||||
<div class="right-panel-items">
|
||||
<div class="project-configuration">
|
||||
<h3 class="dark:text-white">项目配置</h3>
|
||||
<h4 class="dark:text-white">项目配置</h4>
|
||||
<span title="关闭配置">
|
||||
<IconifyIconOffline
|
||||
class="dark:text-white"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import mdiKeyboardEsc from "@/assets/svg/keyboard_esc.svg?component";
|
||||
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from "vue-router";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import SearchResult from "./SearchResult.vue";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { SearchModal } from "./components";
|
||||
import { useBoolean } from "../../hooks/useBoolean";
|
||||
const { bool: show, toggle } = useBoolean();
|
||||
|
||||
@@ -13,7 +13,6 @@ import { useRouter } from "vue-router";
|
||||
import panel from "../panel/index.vue";
|
||||
import { emitter } from "@/utils/mitt";
|
||||
import { resetRouter } from "@/router";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { removeToken } from "@/utils/auth";
|
||||
import { routerArrays } from "@/layout/types";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
@@ -38,9 +37,9 @@ const { isDark } = useDark();
|
||||
const { isSelect } = useCssModule();
|
||||
const { $storage } = useGlobal<GlobalPropertiesApi>();
|
||||
|
||||
const mixRef = templateRef<HTMLElement | null>("mixRef", null);
|
||||
const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
|
||||
const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
|
||||
const mixRef = ref();
|
||||
const verticalRef = ref();
|
||||
const horizontalRef = ref();
|
||||
|
||||
const {
|
||||
body,
|
||||
@@ -54,8 +53,8 @@ const {
|
||||
|
||||
/* body添加layout属性,作用于src/style/sidebar.scss */
|
||||
if (unref(layoutTheme)) {
|
||||
let layout = unref(layoutTheme).layout;
|
||||
let theme = unref(layoutTheme).theme;
|
||||
const layout = unref(layoutTheme).layout;
|
||||
const theme = unref(layoutTheme).theme;
|
||||
toggleTheme({
|
||||
scopeName: `layout-theme-${theme}`
|
||||
});
|
||||
@@ -119,13 +118,13 @@ const weekChange = (value): void => {
|
||||
};
|
||||
|
||||
const tagsChange = () => {
|
||||
let showVal = settings.tabsVal;
|
||||
const showVal = settings.tabsVal;
|
||||
storageConfigureChange("hideTabs", showVal);
|
||||
emitter.emit("tagViewsChange", showVal as unknown as string);
|
||||
};
|
||||
|
||||
const multiTagsCacheChange = () => {
|
||||
let multiTagsCache = settings.multiTagsCache;
|
||||
const multiTagsCache = settings.multiTagsCache;
|
||||
storageConfigureChange("multiTagsCache", multiTagsCache);
|
||||
useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { isEqual } from "lodash-unified";
|
||||
import { isEqual } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { ref, watch, onMounted, toRaw } from "vue";
|
||||
import { getParentPaths, findRouteByPath } from "@/router/utils";
|
||||
|
||||
@@ -11,7 +11,7 @@ import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
import globalization from "@/assets/svg/globalization.svg?component";
|
||||
|
||||
const menuRef = ref();
|
||||
let defaultActive = ref(null);
|
||||
const defaultActive = ref(null);
|
||||
|
||||
const { t, route, locale, translationCh, translationEn } =
|
||||
useTranslationLang(menuRef);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import path from "path";
|
||||
import { getConfig } from "@/config";
|
||||
import { childrenType } from "../../types";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
@@ -76,6 +77,10 @@ const getSpanStyle = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
const expandCloseIcon = computed(() => {
|
||||
return getConfig()?.MenuArrowIconNoTransition ? "expand-close-icon" : "";
|
||||
});
|
||||
|
||||
const onlyOneChild: childrenType = ref(null);
|
||||
// 存放菜单是否存在showTooltip属性标识
|
||||
const hoverMenuMap = new WeakMap();
|
||||
@@ -212,7 +217,15 @@ function resolvePath(routePath) {
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<el-sub-menu v-else ref="subMenu" :index="resolvePath(props.item.path)">
|
||||
<el-sub-menu
|
||||
v-else
|
||||
ref="subMenu"
|
||||
:index="resolvePath(props.item.path)"
|
||||
v-bind:[expandCloseIcon]="useRenderIcon('ep-arrow-down')"
|
||||
:expand-open-icon="useRenderIcon('ep-arrow-up')"
|
||||
:collapse-close-icon="useRenderIcon('ep-arrow-right')"
|
||||
:collapse-open-icon="useRenderIcon('ep-arrow-left')"
|
||||
>
|
||||
<template #title>
|
||||
<div v-if="toRaw(props.item.meta.icon)" class="sub-menu-icon">
|
||||
<component
|
||||
|
||||
@@ -19,7 +19,7 @@ const showLogo = ref(
|
||||
const { routers, device, pureApp, isCollapse, menuSelect, toggleSideBar } =
|
||||
useNav();
|
||||
|
||||
let subMenuData = ref([]);
|
||||
const subMenuData = ref([]);
|
||||
|
||||
const menuData = computed(() => {
|
||||
return pureApp.layout === "mix" && device.value !== "mobile"
|
||||
|
||||
@@ -42,7 +42,7 @@ const {
|
||||
const tabDom = ref();
|
||||
const containerDom = ref();
|
||||
const scrollbarDom = ref();
|
||||
let isShowArrow = ref(false);
|
||||
const isShowArrow = ref(false);
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
|
||||
const dynamicTagView = () => {
|
||||
@@ -129,7 +129,7 @@ function dynamicRouteTag(value: string, parentPath: string): void {
|
||||
function concatPath(arr: object[], value: string, parentPath: string) {
|
||||
if (!hasValue) {
|
||||
arr.forEach((arrItem: any) => {
|
||||
let pathConcat = parentPath + arrItem.path;
|
||||
const pathConcat = parentPath + arrItem.path;
|
||||
if (arrItem.path === value || pathConcat === value) {
|
||||
useMultiTagsStoreHook().handleTags("push", {
|
||||
path: value,
|
||||
@@ -160,7 +160,7 @@ function onFresh() {
|
||||
function deleteDynamicTag(obj: any, current: any, tag?: string) {
|
||||
// 存放被删除的缓存路由
|
||||
let delAliveRouteList = [];
|
||||
let valueIndex: number = multiTags.value.findIndex((item: any) => {
|
||||
const valueIndex: number = multiTags.value.findIndex((item: any) => {
|
||||
if (item.query) {
|
||||
if (item.path === obj.path) {
|
||||
return item.query === obj.query;
|
||||
@@ -199,7 +199,7 @@ function deleteDynamicTag(obj: any, current: any, tag?: string) {
|
||||
// 从当前匹配到的路径中删除
|
||||
spliceRoute(valueIndex, 1);
|
||||
}
|
||||
let newRoute = useMultiTagsStoreHook().handleTags("slice");
|
||||
const newRoute = useMultiTagsStoreHook().handleTags("slice");
|
||||
if (current === route.path) {
|
||||
// 删除缓存路由
|
||||
tag
|
||||
@@ -339,8 +339,8 @@ function showMenuModel(
|
||||
query: object = {},
|
||||
refresh = false
|
||||
) {
|
||||
let allRoute = multiTags.value;
|
||||
let routeLength = multiTags.value.length;
|
||||
const allRoute = multiTags.value;
|
||||
const routeLength = multiTags.value.length;
|
||||
let currentIndex = -1;
|
||||
if (isEmpty(query)) {
|
||||
currentIndex = allRoute.findIndex(v => v.path === currentPath);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, unref, onMounted, nextTick } from "vue";
|
||||
|
||||
@@ -69,7 +69,7 @@ export function useDataThemeChange() {
|
||||
return new TinyColor(color).shade(10).toString();
|
||||
};
|
||||
|
||||
/** 设置ep主题色 */
|
||||
/** 设置 `element-plus` 主题色 */
|
||||
const setEpThemeColor = (color: string) => {
|
||||
useEpThemeStoreHook().setEpThemeColor(color);
|
||||
body.style.setProperty("--el-color-primary-active", shadeBgColor(color));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { computed } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { getConfig } from "@/config";
|
||||
import { useRouter } from "vue-router";
|
||||
import { emitter } from "@/utils/mitt";
|
||||
@@ -10,12 +11,14 @@ import { useAppStoreHook } from "@/store/modules/app";
|
||||
import { i18nChangeLanguage } from "@wangeditor/editor";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
|
||||
const errorInfo = "当前路由配置不正确,请检查配置";
|
||||
|
||||
export function useNav() {
|
||||
const pureApp = useAppStoreHook();
|
||||
const routers = useRouter().options.routes;
|
||||
const { wholeMenus } = storeToRefs(usePermissionStoreHook());
|
||||
|
||||
/** 用户名 */
|
||||
const username = computed(() => {
|
||||
@@ -99,6 +102,7 @@ export function useNav() {
|
||||
}
|
||||
|
||||
function menuSelect(indexPath: string, routers): void {
|
||||
if (wholeMenus.value.length === 0) return;
|
||||
if (isRemaining(indexPath)) return;
|
||||
let parentPath = "";
|
||||
const parentPathIndex = indexPath.lastIndexOf("/");
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { tagsViewsType } from "../types";
|
||||
import { isEqual } from "lodash-unified";
|
||||
import type { StorageConfigs } from "/#/index";
|
||||
import { useEventListener } from "@vueuse/core";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { transformI18n, $t } from "@/plugins/i18n";
|
||||
import { isEqual, isBoolean } from "@pureadmin/utils";
|
||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
import { storageLocal, toggleClass, hasClass } from "@pureadmin/utils";
|
||||
@@ -106,15 +106,14 @@ export function useTags() {
|
||||
]);
|
||||
|
||||
function conditionHandle(item, previous, next) {
|
||||
if (
|
||||
Object.keys(route.query).length === 0 &&
|
||||
Object.keys(route.params).length === 0
|
||||
) {
|
||||
return route.path === item.path ? previous : next;
|
||||
} else if (Object.keys(route.query).length > 0) {
|
||||
return isEqual(route.query, item.query) ? previous : next;
|
||||
if (isBoolean(route?.meta?.showLink) && route?.meta?.showLink === false) {
|
||||
if (Object.keys(route.query).length > 0) {
|
||||
return isEqual(route.query, item.query) ? previous : next;
|
||||
} else {
|
||||
return isEqual(route.params, item.params) ? previous : next;
|
||||
}
|
||||
} else {
|
||||
return isEqual(route.params, item.params) ? previous : next;
|
||||
return route.path === item.path ? previous : next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ let isAutoCloseSidebar = true;
|
||||
// 监听容器
|
||||
emitter.on("resize", ({ detail }) => {
|
||||
if (isMobile) return;
|
||||
let { width } = detail;
|
||||
const { width } = detail;
|
||||
width <= 760 ? setTheme("vertical") : setTheme(useAppStoreHook().layout);
|
||||
/** width app-wrapper类容器宽度
|
||||
* 0 < width <= 760 隐藏侧边栏
|
||||
|
||||
@@ -20,7 +20,6 @@ const themeColors = {
|
||||
menuHover: "#4091f7",
|
||||
subMenuBg: "#0f0303",
|
||||
subMenuActiveBg: "#4091f7",
|
||||
navTextColor: "#fff",
|
||||
menuText: "rgb(254 254 254 / 65%)",
|
||||
sidebarLogo: "#002140",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -33,7 +32,6 @@ const themeColors = {
|
||||
menuHover: "#e0ebf6",
|
||||
subMenuBg: "#fff",
|
||||
subMenuActiveBg: "#e0ebf6",
|
||||
navTextColor: "#7a80b4",
|
||||
menuText: "#7a80b4",
|
||||
sidebarLogo: "#fff",
|
||||
menuTitleHover: "#000",
|
||||
@@ -46,7 +44,6 @@ const themeColors = {
|
||||
menuHover: "#e13c39",
|
||||
subMenuBg: "#000",
|
||||
subMenuActiveBg: "#e13c39",
|
||||
navTextColor: "#red",
|
||||
menuText: "rgb(254 254 254 / 65.1%)",
|
||||
sidebarLogo: "#42090c",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -59,7 +56,6 @@ const themeColors = {
|
||||
menuHover: "#e85f33",
|
||||
subMenuBg: "#0f0603",
|
||||
subMenuActiveBg: "#e85f33",
|
||||
navTextColor: "#fff",
|
||||
menuText: "rgb(254 254 254 / 65%)",
|
||||
sidebarLogo: "#441708",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -72,7 +68,6 @@ const themeColors = {
|
||||
menuHover: "#f6da4d",
|
||||
subMenuBg: "#0f0603",
|
||||
subMenuActiveBg: "#f6da4d",
|
||||
navTextColor: "#fff",
|
||||
menuText: "rgb(254 254 254 / 65%)",
|
||||
sidebarLogo: "#443b05",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -85,7 +80,6 @@ const themeColors = {
|
||||
menuHover: "#59bfc1",
|
||||
subMenuBg: "#000",
|
||||
subMenuActiveBg: "#59bfc1",
|
||||
navTextColor: "#7a80b4",
|
||||
menuText: "#7a80b4",
|
||||
sidebarLogo: "#053434",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -98,7 +92,6 @@ const themeColors = {
|
||||
menuHover: "#60ac80",
|
||||
subMenuBg: "#000",
|
||||
subMenuActiveBg: "#60ac80",
|
||||
navTextColor: "#7a80b4",
|
||||
menuText: "#7a80b4",
|
||||
sidebarLogo: "#112f21",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -111,7 +104,6 @@ const themeColors = {
|
||||
menuHover: "#d84493",
|
||||
subMenuBg: "#000",
|
||||
subMenuActiveBg: "#d84493",
|
||||
navTextColor: "#7a80b4",
|
||||
menuText: "#7a80b4",
|
||||
sidebarLogo: "#3f0d29",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -124,7 +116,6 @@ const themeColors = {
|
||||
menuHover: "#693ac9",
|
||||
subMenuBg: "#000",
|
||||
subMenuActiveBg: "#693ac9",
|
||||
navTextColor: "#7a80b4",
|
||||
menuText: "#7a80b4",
|
||||
sidebarLogo: "#1f0c38",
|
||||
menuTitleHover: "#fff",
|
||||
@@ -147,7 +138,6 @@ export const genScssMultipleScopeVars = (): MultipleScopeVarsItem[] => {
|
||||
$menuHover: ${themeColors[key].menuHover} !default;
|
||||
$subMenuBg: ${themeColors[key].subMenuBg} !default;
|
||||
$subMenuActiveBg: ${themeColors[key].subMenuActiveBg} !default;
|
||||
$navTextColor: ${themeColors[key].navTextColor} !default;
|
||||
$menuText: ${themeColors[key].menuText} !default;
|
||||
$sidebarLogo: ${themeColors[key].sidebarLogo} !default;
|
||||
$menuTitleHover: ${themeColors[key].menuTitleHover} !default;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import "@/utils/sso";
|
||||
import { getConfig } from "@/config";
|
||||
import { toRouteType } from "./types";
|
||||
import NProgress from "@/utils/progress";
|
||||
@@ -33,6 +34,7 @@ import pptRouter from "./modules/ppt";
|
||||
import homeRouter from "./modules/home";
|
||||
import ableRouter from "./modules/able";
|
||||
import listRouter from "./modules/list";
|
||||
import tableRouter from "./modules/table";
|
||||
import aboutRouter from "./modules/about";
|
||||
import errorRouter from "./modules/error";
|
||||
import guideRouter from "./modules/guide";
|
||||
@@ -50,6 +52,7 @@ const routes = [
|
||||
homeRouter,
|
||||
ableRouter,
|
||||
listRouter,
|
||||
tableRouter,
|
||||
aboutRouter,
|
||||
errorRouter,
|
||||
guideRouter,
|
||||
@@ -134,6 +137,10 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
else document.title = transformI18n(item.meta.title);
|
||||
});
|
||||
}
|
||||
/** 如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面 */
|
||||
function toCorrectRoute() {
|
||||
whiteList.includes(to.fullPath) ? next(_from.fullPath) : next();
|
||||
}
|
||||
if (userInfo) {
|
||||
// 无权限跳转403页面
|
||||
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
||||
@@ -145,7 +152,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
openLink(to?.name as string);
|
||||
NProgress.done();
|
||||
} else {
|
||||
next();
|
||||
toCorrectRoute();
|
||||
}
|
||||
} else {
|
||||
// 刷新
|
||||
@@ -175,7 +182,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
}
|
||||
router.push(to.fullPath);
|
||||
});
|
||||
next();
|
||||
toCorrectRoute();
|
||||
}
|
||||
} else {
|
||||
if (to.path !== "/login") {
|
||||
|
||||
@@ -7,7 +7,7 @@ const ableRouter: RouteConfigsTable = {
|
||||
meta: {
|
||||
icon: "ubuntu-fill",
|
||||
title: $t("menus.hsAble"),
|
||||
rank: 4
|
||||
rank: 5
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ const componentsRouter: RouteConfigsTable = {
|
||||
meta: {
|
||||
icon: "menu",
|
||||
title: $t("menus.hscomponents"),
|
||||
rank: 5
|
||||
rank: 6
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import type { RouteConfigsTable } from "/#/index";
|
||||
const IFrame = () => import("@/layout/frameView.vue");
|
||||
|
||||
const formDesignRouter: RouteConfigsTable = {
|
||||
path: "/formDesign",
|
||||
@@ -13,9 +14,11 @@ const formDesignRouter: RouteConfigsTable = {
|
||||
{
|
||||
path: "/formDesign/index",
|
||||
name: "FormDesign",
|
||||
component: () => import("@/views/form-design/index.vue"),
|
||||
component: IFrame,
|
||||
meta: {
|
||||
title: $t("menus.hsFormDesign")
|
||||
title: $t("menus.hsFormDesign"),
|
||||
frameSrc:
|
||||
"https://haixin-fang.github.io/starfish-vue3-lowcode/playground/index.html#/"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -7,7 +7,7 @@ const nestedRouter: RouteConfigsTable = {
|
||||
meta: {
|
||||
title: $t("menus.hsmenus"),
|
||||
icon: "histogram",
|
||||
rank: 6
|
||||
rank: 7
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -17,11 +17,7 @@ const pptRouter: RouteConfigsTable = {
|
||||
meta: {
|
||||
title: "PPT",
|
||||
frameSrc: "https://pipipi-pikachu.github.io/PPTist/",
|
||||
frameLoading: false,
|
||||
extraIcon: {
|
||||
svg: true,
|
||||
name: "team-iconxinpin"
|
||||
}
|
||||
frameLoading: false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
27
src/router/modules/table.ts
Normal file
27
src/router/modules/table.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { RouteConfigsTable } from "/#/index";
|
||||
|
||||
const flowChartRouter: RouteConfigsTable = {
|
||||
path: "/pure-table",
|
||||
redirect: "/pure-table/index",
|
||||
meta: {
|
||||
icon: "mdi:table-large",
|
||||
title: "pure-admin-table",
|
||||
rank: 4
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/pure-table/index",
|
||||
name: "PureTable",
|
||||
component: () => import("@/views/pure-table/index.vue"),
|
||||
meta: {
|
||||
title: "pure-admin-table",
|
||||
extraIcon: {
|
||||
svg: true,
|
||||
name: "team-iconxinpin"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default flowChartRouter;
|
||||
@@ -76,7 +76,7 @@ function isOneOfArray(a: Array<string>, b: Array<string>) {
|
||||
/** 从sessionStorage里取出当前登陆用户的角色roles,过滤无权限的菜单 */
|
||||
function filterNoPermissionTree(data: RouteComponent[]) {
|
||||
const currentRoles =
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey).roles ?? [];
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey)?.roles ?? [];
|
||||
const newTree = cloneDeep(data).filter((v: any) =>
|
||||
isOneOfArray(v.meta?.roles, currentRoles)
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { store } from "@/store";
|
||||
import { isEqual } from "lodash-unified";
|
||||
import { isEqual } from "@pureadmin/utils";
|
||||
import type { StorageConfigs } from "/#/index";
|
||||
import { routerArrays } from "@/layout/types";
|
||||
import { multiType, positionType } from "./types";
|
||||
@@ -11,11 +11,11 @@ export const useMultiTagsStore = defineStore({
|
||||
state: () => ({
|
||||
// 存储标签页信息(路由信息)
|
||||
multiTags: storageLocal.getItem<StorageConfigs>("responsive-configure")
|
||||
.multiTagsCache
|
||||
?.multiTagsCache
|
||||
? storageLocal.getItem<StorageConfigs>("responsive-tags")
|
||||
: [...routerArrays],
|
||||
multiTagsCache: storageLocal.getItem<StorageConfigs>("responsive-configure")
|
||||
.multiTagsCache
|
||||
?.multiTagsCache
|
||||
}),
|
||||
getters: {
|
||||
getMultiTagsCache() {
|
||||
|
||||
@@ -59,9 +59,9 @@ export const useUserStore = defineStore({
|
||||
this.username = "";
|
||||
this.roles = [];
|
||||
removeToken();
|
||||
router.push("/login");
|
||||
useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
|
||||
resetRouter();
|
||||
router.push("/login");
|
||||
},
|
||||
/** 刷新`token` */
|
||||
async handRefreshToken(data) {
|
||||
|
||||
@@ -129,7 +129,7 @@ html.dark {
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.vxe-button.type--button.size--medium:hover {
|
||||
.vxe-button.type--button:hover {
|
||||
background: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
@@ -170,6 +170,12 @@ html.dark {
|
||||
}
|
||||
}
|
||||
|
||||
/* intro.js */
|
||||
.introjs-tooltip-title,
|
||||
.introjs-tooltiptext {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
/* element-plus */
|
||||
.el-table__cell {
|
||||
background: var(--el-bg-color);
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
filter: invert(80%);
|
||||
}
|
||||
|
||||
/* 重置 vxe-table 中 pager 样式 */
|
||||
/* 重置 vxe-table 样式 */
|
||||
.vxe-button.type--button.theme--primary:hover,
|
||||
.vxe-pager .vxe-pager--num-btn:not(.is--disabled).is--active {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
@@ -44,16 +44,6 @@ abbr:where([title]) {
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
|
||||
@@ -68,10 +68,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.el-popper.is-light {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
/* 展开动画 */
|
||||
transition: width var(--pure-transition-duration);
|
||||
@@ -233,11 +229,9 @@
|
||||
.search-container,
|
||||
/* 告警 */
|
||||
.dropdown-badge,
|
||||
/* 全屏 */
|
||||
.screen-full,
|
||||
/* 国际化 */
|
||||
.globalization,
|
||||
/* 登录名 */
|
||||
/* 用户名 */
|
||||
.el-dropdown-link,
|
||||
/* 设置 */
|
||||
.set-icon {
|
||||
@@ -587,11 +581,9 @@ body[layout="vertical"] {
|
||||
.search-container,
|
||||
/* 告警 */
|
||||
.dropdown-badge,
|
||||
/* 全屏 */
|
||||
.screen-full,
|
||||
/* 国际化 */
|
||||
.globalization,
|
||||
/* 登录名 */
|
||||
/* 用户名 */
|
||||
.el-dropdown-link,
|
||||
/* 设置 */
|
||||
.set-icon {
|
||||
|
||||
@@ -40,16 +40,3 @@
|
||||
.breadcrumb-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 重置el-menu的展开收起动画时长
|
||||
* @see {@link https://github.com/element-plus/element-plus/issues/4509#issuecomment-980165001}
|
||||
*/
|
||||
.outer-most .el-collapse-transition-leave-active,
|
||||
.outer-most .el-collapse-transition-enter-active {
|
||||
transition: 0.12s all ease-in-out !important;
|
||||
}
|
||||
|
||||
.horizontal-collapse-transition {
|
||||
transition: var(--pure-transition-duration) all !important;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
### 注意
|
||||
|
||||
- `vue-pure-admin` 从 `3.3.0` 版本之后(不包括 `3.3.0` 版本),大部分工具和 `hooks` 都集成到了[@pureadmin/utils](https://xiaoxian521.github.io/pure-admin-utils-docs/)
|
||||
- `vue-pure-admin` 从 `3.3.0` 版本之后(不包括 `3.3.0` 版本),大部分工具和 `hooks` 都集成到了 [@pureadmin/utils](https://pure-admin-utils.netlify.app/)
|
||||
- [npm](https://www.npmjs.com/package/@pureadmin/utils)
|
||||
- [文档代码地址](https://github.com/xiaoxian521/pure-admin-utils-docs)
|
||||
|
||||
@@ -35,7 +35,7 @@ export function getToken(): DataInfo<number> {
|
||||
export function setToken(data: DataInfo<Date>) {
|
||||
let expires = 0;
|
||||
const { accessToken, refreshToken } = data;
|
||||
expires = new Date(data.expires).getTime();
|
||||
expires = new Date(data.expires).getTime(); // 如果后端直接设置时间戳,将此处代码改为expires = data.expires,然后把上面的DataInfo<Date>改成DataInfo<number>即可
|
||||
const cookieString = JSON.stringify({ accessToken, expires });
|
||||
|
||||
expires > 0
|
||||
@@ -59,8 +59,10 @@ export function setToken(data: DataInfo<Date>) {
|
||||
const { username, roles } = data;
|
||||
setSessionKey(username, roles);
|
||||
} else {
|
||||
const { username, roles } =
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey);
|
||||
const username =
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey)?.username ?? "";
|
||||
const roles =
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey)?.roles ?? [];
|
||||
setSessionKey(username, roles);
|
||||
}
|
||||
}
|
||||
|
||||
7
src/utils/globalPolyfills.ts
Normal file
7
src/utils/globalPolyfills.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// 如果项目出现 `global is not defined` 报错,可能是您引入某个库的问题,比如 aws-sdk-js https://github.com/aws/aws-sdk-js
|
||||
// 解决办法就是将该文件引入 src/main.ts 即可 import "@/utils/globalPolyfills";
|
||||
if (typeof (window as any).global === "undefined") {
|
||||
(window as any).global = window;
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -1,25 +0,0 @@
|
||||
## 用法
|
||||
|
||||
### Get 请求
|
||||
|
||||
```
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
// params传参
|
||||
http.request('get', '/xxx', { params: param });
|
||||
|
||||
// url拼接传参
|
||||
http.request('get', '/xxx?message=' + msg);
|
||||
```
|
||||
|
||||
### Post 请求
|
||||
|
||||
```
|
||||
import { http } from "@/utils/http";
|
||||
|
||||
// params传参
|
||||
http.request('post', '/xxx', { params: param });
|
||||
|
||||
// data传参
|
||||
http.request('post', '/xxx', { data: param });
|
||||
```
|
||||
@@ -11,21 +11,12 @@ import {
|
||||
} from "./types.d";
|
||||
import { stringify } from "qs";
|
||||
import NProgress from "../progress";
|
||||
// import { loadEnv } from "@build/index";
|
||||
import { getToken, formatToken } from "@/utils/auth";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
|
||||
// 加载环境变量 VITE_PROXY_DOMAIN(开发环境) VITE_PROXY_DOMAIN_REAL(打包后的线上环境)
|
||||
// const { VITE_PROXY_DOMAIN, VITE_PROXY_DOMAIN_REAL } = loadEnv();
|
||||
|
||||
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
|
||||
const defaultConfig: AxiosRequestConfig = {
|
||||
// baseURL:
|
||||
// process.env.NODE_ENV === "production"
|
||||
// ? VITE_PROXY_DOMAIN_REAL
|
||||
// : VITE_PROXY_DOMAIN,
|
||||
// 当前使用mock模拟请求,将baseURL制空,如果你的环境用到了http请求,请删除下面的baseURL启用上面的baseURL,并将第14行、19行代码注释取消
|
||||
baseURL: "",
|
||||
// 请求超时时间
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
Accept: "application/json, text/plain, */*",
|
||||
|
||||
59
src/utils/sso.ts
Normal file
59
src/utils/sso.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { removeToken, setToken, type DataInfo } from "./auth";
|
||||
import { subBefore, getQueryMap } from "@pureadmin/utils";
|
||||
|
||||
/**
|
||||
* 简版前端单点登录,根据实际业务自行编写,平台启动后本地可以跳后面这个链接进行测试 http://localhost:8848/#/permission/page/index?username=sso&roles=admin&accessToken=eyJhbGciOiJIUzUxMiJ9.admin
|
||||
* 划重点:
|
||||
* 判断是否为单点登录,不为则直接返回不再进行任何逻辑处理,下面是单点登录后的逻辑处理
|
||||
* 1.清空本地旧信息;
|
||||
* 2.获取url中的重要参数信息,然后通过 setToken 保存在本地;
|
||||
* 3.删除不需要显示在 url 的参数
|
||||
* 4.使用 window.location.replace 跳转正确页面
|
||||
*/
|
||||
(function () {
|
||||
// 获取 url 中的参数
|
||||
const params = getQueryMap(location.href) as DataInfo<Date>;
|
||||
const must = ["username", "roles", "accessToken"];
|
||||
const mustLength = must.length;
|
||||
if (Object.keys(params).length !== mustLength) return;
|
||||
|
||||
// url 参数满足 must 里的全部值,才判定为单点登录,避免非单点登录时刷新页面无限循环
|
||||
let sso = [];
|
||||
let start = 0;
|
||||
|
||||
while (start < mustLength) {
|
||||
if (Object.keys(params).includes(must[start]) && sso.length <= mustLength) {
|
||||
sso.push(must[start]);
|
||||
} else {
|
||||
sso = [];
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
if (sso.length === mustLength) {
|
||||
// 判定为单点登录
|
||||
|
||||
// 清空本地旧信息
|
||||
removeToken();
|
||||
|
||||
// 保存新信息到本地
|
||||
setToken(params);
|
||||
|
||||
// 删除不需要显示在 url 的参数
|
||||
delete params["roles"];
|
||||
delete params["accessToken"];
|
||||
|
||||
const newUrl = `${location.origin}${location.pathname}${subBefore(
|
||||
location.hash,
|
||||
"?"
|
||||
)}?${JSON.stringify(params)
|
||||
.replace(/["{}]/g, "")
|
||||
.replace(/:/g, "=")
|
||||
.replace(/,/g, "&")}`;
|
||||
|
||||
// 替换历史记录项
|
||||
window.location.replace(newUrl);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
})();
|
||||
@@ -11,12 +11,12 @@ defineOptions({
|
||||
name: "Download"
|
||||
});
|
||||
|
||||
let base64 =
|
||||
const base64 =
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALEAAAAwCAYAAABexZu4AAAAAXNSR0IArs4c6QAAC5pJREFUeF7tnQ9wFNUdx7+/vQQsiOb2orHyp0JuQ/1TpFVbS+2I7RS1aqdlKu2oU2WqQvbQFmtrO7QFpp22U0ZhgNuQInXa6rTFKo5oi3XGPzNqiwIWBDTZS2Boi8aQDQxYId7tr/M2CZNc7u69vdtLLrI7k2GG/b3fe+/3Pvu737597/cIRVw1ydaZEWAmE13MwEwCojj5R+PA/B4IxwA6RuD3uPff3UzYRhneU/X++7s7vn/xe0VUHRYJLTDEAqRqk5qV+2q0senbANwKYKZquVxyBHQy0eNw+XEnYfy9FF0jWbZmjT1bVv/hu4wXZDK57st0V42pbjm04Ly3i9FdzjKnr7bPqiJcWKiOYm2ST6cSxHqyZRkocivA5wVvAH7NMRs+raR34+4xNR1jZ1VrJ7Z1Ji46plSmTEJRy36eACnEbgZX+R00Vd2OaSiNX5lMkFOtbtksq4+BF7pN4yqZnOr9gkbQ19uT8AEeAHCjqkLfckRvOI3xGYXKCa+kRehegL8A4CN9sq8A2qOOWb/Kd50BFFAFLYR4qLGHDWLdap0P0G8DGO+CKgi0rsuMN+YTija1XU/sbs6rhPmPTqLhpnK3M1t/CHFui1eMJ44lW29jooeGAwwm3NLdaDySq67aDZ0T3BOH3wJwbqG2cET7fPeC+peGo739dYQQVzDEsWTbZUzuq8MFhEvpqYcbz9+fqz49aX8bhAcV2rLBMY3bFeQCEwkhrlCI61bsHN8zftyLBFwS2GgXVrTHMY2L8onoVmszQHcqtKWwnnX2BewiKdNDGhLOQmOvTE7cDyGuUIhjVurHDP6ZyiAGJFPQg+pW6jGA58rrYscxG2L55HpfDPG8TI+fl7AQ4gqEONrcdialM6+DaKpssIfcJ7wFF7tAfICAA3DpgKtpaWL3HCLUMXMdiOoYqBs0LcW43UkYG/LVF2tKLWLmNdL2SF7uQoilFgxMYERf7HTL/i6Alb56w+5ykLbFMY1/+innQaW5s92eMasOL556OF/ZM9fan9I0vELA2IL6JQ9DCLGf0SlNduQg3sgR/VDbDoALztcO6p6GC1Xjx1LMEk3avyTCDwvoeMYxjWsK1RFCXMoI+Cs7YhDH1rXNZdd9TLW5THRFd2P8ZVX5UuV6vxhqS7P1EOORyJjI9969Y1pHCHGpVg6m/IhBHG1K/ZyYl6h0g4AlXabxCxXZIGX0ZOoaBl8JwuXE2A7CVsc0HlWpI/TEKlYKRmbEINYt+xkAc2TdYGB7t2lcKpOrtPshxMM3IiMD8VLW9LqUWEzTvyYhb48ZtKDbjP9m+EwSTE0hxMHYUUVLMRDrydQsIDOHNS1GzLUgisHlQwy0E1O7y2gvtIiKate1Xeq67msKDTzomMZEBbnARHx8/p6XK7Q4e317XbonczFAM0C8opSG9aRx9rG7jc5+HZU4TxxN2kkQLijUTw042mUaX5HZQvRPJkPsvugkpi8bKKcKcSRSfZObPrGASbuZgLisLoB2gTObsusT5Uh1ao2AzSqdlzdGXSLfC90QDewu7+9cbfP+j3Km56cswAXE3+nqNeaXzP4QUokQqwAkeqiyhFNFV67VaKrlVJax5hmNIV9nSU/aD4CwWDrQA0CRygYkUAzEymV8trEUiH1WBYpgqcogZ8OoAlAlQOzXHtnyDKS6TcPo/3+KJu3fEeFbMsVM2g3djfVPyeSCvK8M5IAHTLmMz4YWC7HPanyJn6oQ9xnpUcc05nnhRKzJ3syM62XW0zTtskML67cVkvMAKvJiihzMfmlUBjKE2LP6qeKJT3pgjW7tWhj/PelN9itgfFbGXkTTGjoX1tv55JSBK1DREM+S5yNHoZhYb7KXglH0w5SveaEnHmqZYmNiGWs+7j/nmMYXSbdSLQA3yApWE9V1NMbfDSHutYDqi53MrqXcP8XDiV7TMV0rZicOAci7jLHfyHoap6XuNk5UPMSq3tsnPaEnDt4TE/A6AzuI+aWMS97GCNJwtWStzOCGMO4XEEt3p4pSThqnYRRALNqaa7u76nrifGxnT7aHnhgoIZz4mwb6ySEzvj2vU7TsbjGUCr5mJ+lWa5eYLpYJZ0/2Z8tXSkycqx8j+cVOZtdS7o/acEJhuja6ru3L5LpPq9iHopZtq3wxyUQQP7LAaKv0cCKEWD7sI/2xAwoQi17oVuurAF0m65EIJ8SC9s/IBDMuLjmyyNgRQuzzxY6wDK7rK8kJk3blh/pjhzLE9p8AfEPGpoD4rwCulQnK9p+F4URuC8rslquUarz9YQ4nej2xfT+Ae2RsUixpP8yEm2WCYLrXScSF0rxXvvxhKi9V3stjVlom5QdD8mSPZEwcQpwDF3VPrLRljqJW62oC3SWHuPhMO8ozICHE3jCEnriXxpjV8lWGtknGJil7O6DVMY3pMoW57ocQ+8uMGULcS5GebJ8DyogNGwUvqrVSl7jggmsi+jUU89PYF9uozUWHnjj0xANw1ZP210GQbkHz3pp1y/6vLN+ZkGOG1Z0wErInI/t+6IlDTzyICeWYuG0+4EqTWvZBrJYuihmdFMFsv1v1Q4hDiIuCONn6HRBJU/d6EEct+xYC/qDoYQvmPQtj4sEWKCYEC2Pi/hc7tbRqHsQ1a/d+TNOqc2amzAWl3yTJoSeuLE9M5E7qapwuQsi8l8qYFb12QjGciFn2DgY+KXOuJ78kRS17LQHK8a7ogKZpa7oW1j8uq0TFIEJHueaJo02pz4mVUrJ2QpIOa2B5VW85zJ5Y7FofL+unSptUxqycEOtrW78EjVTOczl6EmJ9tX0BqrDV/8ZKeo3ALQzaT8StYPdthhZlUBTgKBhTiGDKDFtOiGut9ukuMiJZt+wSCVkulwn1hWAVd2aHbqX2qZ2rQiscM/6DfP3Um+yrwdgis0MpEFf/7/iKQidoKe/9BHYO+qYfs+xfMXCfrPHlul8uTzyhuaW2OqOd3G4vaf/LGvBrYtrbmYinvHNLTmCys8j4R+V7YrUFM14/2F2uRaqeihw99qY77owJGUqLQ4XEAyyS6EiXIXgqchwgo+LB++x4kEBPZjL8Z1Sl94tE67GmFpESYiKY5jNooRJnTM2DII6u2j2Fxpy2FeBzlBQELFQuiEUzfRg3d6+y4rhKDCdE3gnVX70ghq5EiINoAth1rxuyusrnTEUgDelXUmaIN5Z0CtRogFh2SE+go1WyJw6iNe2OadTnXCIYs+wEA2uDqMWPjnJCHLVSdxK42U97BsmOBoi9ROnubhAmFd1PHwUrwBMvdkxjVd51rjHL/hEDw5r9spwQn/Hgv/WqnuNvqHyZzDmOowBiL2xqsheDvbMHy36NJMQMeqLbjH9NdLLwYYyWfaOXHUhhS3/JFmPe5CQaBp3Pobw4SXHeMdpk30yMh4tq6yiBuC/+Ly10GmggRgcIdbls5h9iehrg64qy/+BCe6BhXv+XY6UdB97T7eKeMv1MPZZJ474jdw/d+hQ0xN4AJ+05IIiE4v5ytI0iiAMC+TjAawESx8GJh2LI5R9izBNHVzBhCRgfLxLmQQBLPfHASsTB09URnktEwltKcxlLGriFiZ+PUOS5QlmF+hazi4Ma8x7G6K3nICRUE26LdkXXvPkJqqoSJ6beBHEojsqVBXHMsp9k4AZZUdkG21zlVXXL9sr1JYsUefamyNo54P4eAM8yIg91m9N2eZlFP8i8kxPiHAvCCs4CVWOyc4fxHxHaRXqO30HgbwKketj9QbC7Xqsa25x9MLuSJ87ugAB6rOZewRSZxuBpBExjwlkERAUj3p/3M8QdAL3DQAeBO5h4ezrjPnt00fldPoxaNtGalftqImN7ZgPa5Sz6AHh9AZAB0AJGi0gsThG84HfRU9kaXYRiXYSFvXPAE8E8EUTnEjCRAbHTvb03D3Bmnwt64nCi4V9FVFF0EW+5JTDL+5UXfy4me/+e5EfbC3L/kuHjzx0xZ4ht/EOu/wNFbO2YhmAeMQAAAABJRU5ErkJggg==";
|
||||
|
||||
function down() {
|
||||
axios
|
||||
.get("https://xiaoxian521.github.io/pure-admin-utils-docs/logo.png", {
|
||||
.get("https://xiaoxian521.github.io/pure-admin-doc/img/pure.png", {
|
||||
responseType: "blob"
|
||||
})
|
||||
.then(({ data }) => {
|
||||
@@ -34,7 +34,7 @@ function down() {
|
||||
<el-button
|
||||
@click="
|
||||
downloadByOnlineUrl(
|
||||
'https://xiaoxian521.github.io/pure-admin-utils-docs/logo.png',
|
||||
'https://xiaoxian521.github.io/pure-admin-doc/img/pure.png',
|
||||
'test-url.png'
|
||||
)
|
||||
"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { utils, writeFile } from "xlsx";
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "IconSelect"
|
||||
});
|
||||
|
||||
let icon = ref("ep:add-location");
|
||||
const icon = ref("ep:add-location");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { default as vElTableInfiniteScroll } from "el-table-infinite-scroll";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { clone } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import ElTreeLine from "@/components/ReTreeLine";
|
||||
import { extractPathList, deleteChildren } from "@pureadmin/utils";
|
||||
@@ -10,12 +10,12 @@ defineOptions({
|
||||
name: "LineTree"
|
||||
});
|
||||
|
||||
let menusTree = cloneDeep(usePermissionStoreHook().wholeMenus);
|
||||
let menusData = computed(() => {
|
||||
const menusTree = clone(usePermissionStoreHook().wholeMenus, true);
|
||||
const menusData = computed(() => {
|
||||
return deleteChildren(menusTree);
|
||||
});
|
||||
let expandedKeys = extractPathList(menusData.value);
|
||||
let dataProps = {
|
||||
const expandedKeys = extractPathList(menusData.value);
|
||||
const dataProps = {
|
||||
value: "uniqueId",
|
||||
children: "children"
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { clone } from "@pureadmin/utils";
|
||||
import type { ElTreeV2 } from "element-plus";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
@@ -19,18 +19,18 @@ interface treeNode extends TreeNode {
|
||||
}
|
||||
|
||||
const query = ref("");
|
||||
let dataProps = ref({
|
||||
const dataProps = ref({
|
||||
value: "uniqueId",
|
||||
children: "children"
|
||||
});
|
||||
const treeRef = ref<InstanceType<typeof ElTreeV2>>();
|
||||
let menusTree = cloneDeep(usePermissionStoreHook().wholeMenus);
|
||||
const menusTree = clone(usePermissionStoreHook().wholeMenus, true);
|
||||
|
||||
let menusData = computed(() => {
|
||||
const menusData = computed(() => {
|
||||
return deleteChildren(menusTree);
|
||||
});
|
||||
|
||||
let expandedKeys = extractPathList(menusData.value);
|
||||
const expandedKeys = extractPathList(menusData.value);
|
||||
|
||||
const onQueryChanged = (query: string) => {
|
||||
(treeRef as any).value!.filter(query);
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import VuePdfEmbed, {
|
||||
type VuePdfEmbedMethods,
|
||||
type VuePdfEmbedData
|
||||
} from "vue-pdf-embed";
|
||||
import VuePdfEmbed from "vue-pdf-embed";
|
||||
|
||||
defineOptions({
|
||||
name: "Pdf"
|
||||
});
|
||||
|
||||
interface pdfRefType extends VuePdfEmbedData, VuePdfEmbedMethods {}
|
||||
|
||||
const { t } = useI18n();
|
||||
const pdfRef = ref<pdfRefType>();
|
||||
let pageCount = ref(1);
|
||||
let loading = ref(true);
|
||||
let currentPage = ref(1);
|
||||
let currentRotation = ref(0);
|
||||
let showAllPages = ref(false);
|
||||
const pdfRef = ref<any>();
|
||||
const pageCount = ref(1);
|
||||
const loading = ref(true);
|
||||
const currentPage = ref(1);
|
||||
const currentRotation = ref(0);
|
||||
const showAllPages = ref(false);
|
||||
const rotations = [0, 90, 180, 270];
|
||||
|
||||
const source =
|
||||
|
||||
@@ -77,7 +77,7 @@ const options = [
|
||||
];
|
||||
|
||||
function onPrint() {
|
||||
let el = options.filter(v => v.value === value.value)[0]?.el;
|
||||
const el = options.filter(v => v.value === value.value)[0]?.el;
|
||||
Print(el).toPrint;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import "swiper/css";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/pagination";
|
||||
import type { SwiperOptions } from "swiper";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import SwiperCore, { Autoplay, Navigation, Pagination } from "swiper";
|
||||
|
||||
@@ -10,27 +9,9 @@ defineOptions({
|
||||
name: "Swiper"
|
||||
});
|
||||
|
||||
type SwiperExampleOptions = Pick<
|
||||
SwiperOptions,
|
||||
| "navigation"
|
||||
| "pagination"
|
||||
| "scrollbar"
|
||||
| "slidesPerView"
|
||||
| "slidesPerGroup"
|
||||
| "spaceBetween"
|
||||
| "direction"
|
||||
| "loop"
|
||||
| "loopFillGroupWithBlank"
|
||||
| "autoplay"
|
||||
>;
|
||||
interface SwiperExample {
|
||||
id: number;
|
||||
label: string;
|
||||
options: Partial<SwiperExampleOptions>;
|
||||
}
|
||||
SwiperCore.use([Autoplay, Navigation, Pagination]);
|
||||
|
||||
const swiperExample: SwiperExample[] = [
|
||||
const swiperExample: any[] = [
|
||||
{ id: 0, label: "Default", options: {} },
|
||||
{
|
||||
id: 1,
|
||||
@@ -119,7 +100,7 @@ const swiperExample: SwiperExample[] = [
|
||||
</template>
|
||||
<el-row :gutter="10">
|
||||
<el-col v-for="item in swiperExample" :key="item.id" :span="12">
|
||||
<h3 class="py-[24px] text-[24px] font-bold">{{ item.label }}</h3>
|
||||
<h6 class="py-[24px] text-[24px] font-bold">{{ item.label }}</h6>
|
||||
<swiper v-bind="item.options">
|
||||
<swiper-slide v-for="i in 5" :key="i">
|
||||
<div
|
||||
|
||||
@@ -1,21 +1,43 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted, nextTick, onBeforeUnmount } from "vue";
|
||||
import { useWatermark } from "@pureadmin/utils";
|
||||
|
||||
defineOptions({
|
||||
name: "WaterMark"
|
||||
});
|
||||
|
||||
let color = ref("#409EFF");
|
||||
let value = ref("vue-pure-admin");
|
||||
const local = ref();
|
||||
const preventLocal = ref();
|
||||
const color = ref("#409EFF");
|
||||
const value = ref("vue-pure-admin");
|
||||
const { setWatermark, clear } = useWatermark();
|
||||
const { setWatermark: setLocalWatermark, clear: clearLocal } =
|
||||
useWatermark(local);
|
||||
const { setWatermark: setPreventLocalWatermark } = useWatermark(preventLocal);
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
setPreventLocalWatermark("无法删除的水印", {
|
||||
forever: true,
|
||||
width: 187,
|
||||
height: 80
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 在离开该页面时清除整页水印
|
||||
clear();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="font-medium">页面水印功能</span>
|
||||
<span class="font-medium">
|
||||
页面水印功能(将平台主题改为亮白色观察水印效果更明显哦)
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<span> 请输入要创建水印的值:</span>
|
||||
@@ -29,10 +51,132 @@ const { setWatermark, clear } = useWatermark();
|
||||
<el-color-picker v-model="color" show-alpha />
|
||||
<br />
|
||||
<el-button @click="setWatermark(value, { fillStyle: color })">
|
||||
创建
|
||||
创建整页水印
|
||||
</el-button>
|
||||
<el-button @click="clear">清除</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setWatermark(value, {
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建整页渐变水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setWatermark(value, {
|
||||
rotate: 0,
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建整页渐变且水平90度的水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setWatermark(value, {
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
],
|
||||
shadowConfig: [20]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建整页渐变且有阴影的水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setWatermark(value, {
|
||||
globalAlpha: 0.15, // 值越低越透明
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建整页高透明渐变水印
|
||||
</el-button>
|
||||
<el-button @click="clear">清除整页水印</el-button>
|
||||
|
||||
<div
|
||||
ref="local"
|
||||
class="mt-4 mb-4 w-[1080px] h-[400px] border-dotted border-2 border-sky-500"
|
||||
/>
|
||||
<el-button
|
||||
@click="
|
||||
setLocalWatermark('局部水印', {
|
||||
fillStyle: color,
|
||||
width: 140,
|
||||
height: 60
|
||||
})
|
||||
"
|
||||
>
|
||||
创建局部水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setLocalWatermark('局部水印', {
|
||||
width: 140,
|
||||
height: 60,
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建局部渐变水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setLocalWatermark('局部水印', {
|
||||
width: 140,
|
||||
height: 56.5,
|
||||
rotate: 0,
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建局部渐变且水平90度的水印
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
setLocalWatermark('局部水印', {
|
||||
width: 140,
|
||||
height: 56.5,
|
||||
gradient: [
|
||||
{ value: 0, color: 'magenta' },
|
||||
{ value: 0.5, color: 'blue' },
|
||||
{ value: 1.0, color: 'red' }
|
||||
],
|
||||
shadowConfig: [20]
|
||||
})
|
||||
"
|
||||
>
|
||||
创建局部渐变且有阴影的水印
|
||||
</el-button>
|
||||
<el-button @click="clearLocal">清除局部水印</el-button>
|
||||
|
||||
<div
|
||||
ref="preventLocal"
|
||||
class="mt-4 mb-4 w-[1080px] h-[400px] border-dotted border-2 border-indigo-500"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -18,7 +18,10 @@ export function useColumns() {
|
||||
label: "文档地址",
|
||||
cellRenderer: () => {
|
||||
return (
|
||||
<a href="http://yiming_chang.gitee.io/pure-admin-doc" target="_blank">
|
||||
<a
|
||||
href="https://yiming_chang.gitee.io/pure-admin-doc"
|
||||
target="_blank"
|
||||
>
|
||||
<span style="color: var(--el-color-primary)">文档地址</span>
|
||||
</a>
|
||||
);
|
||||
@@ -28,7 +31,10 @@ export function useColumns() {
|
||||
label: "预览地址",
|
||||
cellRenderer: () => {
|
||||
return (
|
||||
<a href="http://yiming_chang.gitee.io/vue-pure-admin" target="_blank">
|
||||
<a
|
||||
href="https://yiming_chang.gitee.io/vue-pure-admin"
|
||||
target="_blank"
|
||||
>
|
||||
<span style="color: var(--el-color-primary)">预览地址</span>
|
||||
</a>
|
||||
);
|
||||
|
||||
@@ -7,14 +7,14 @@ defineOptions({
|
||||
name: "Cropping"
|
||||
});
|
||||
|
||||
let refCropper = ref();
|
||||
let info = ref<object>(null);
|
||||
let cropperImg = ref<string>("");
|
||||
const refCropper = ref();
|
||||
const info = ref<object>(null);
|
||||
const cropperImg = ref<string>("");
|
||||
|
||||
const onCropper = (): void => {
|
||||
nextTick(() => {
|
||||
refCropper.value.cropper.getCroppedCanvas().toBlob(blob => {
|
||||
let fileReader: FileReader = new FileReader();
|
||||
const fileReader: FileReader = new FileReader();
|
||||
fileReader.onloadend = (e: ProgressEvent) => {
|
||||
cropperImg.value = (e.target as any).result;
|
||||
info.value = refCropper.value.cropper.getData();
|
||||
|
||||
@@ -19,432 +19,7 @@ const customDanmus = [
|
||||
}
|
||||
];
|
||||
|
||||
// 弹幕来自b站首页
|
||||
const danmus = [
|
||||
"草",
|
||||
"高技术力",
|
||||
"汤姆逊波纹疾走…啊哒哒哒哒哒哒……",
|
||||
"此曲一出,非死即伤",
|
||||
"这播放量不应该啊",
|
||||
"牛皮!",
|
||||
"全 文 背 诵",
|
||||
"ohhhhhhh",
|
||||
"NICE",
|
||||
"草这死亡姿势",
|
||||
"日常迫害团长",
|
||||
"溜了溜了",
|
||||
"火钳刘明",
|
||||
"真实",
|
||||
"汤姆逊波纹疾走",
|
||||
"不 要 停 下 来 啊",
|
||||
"泥 给 路 打 油",
|
||||
"停下来了",
|
||||
"草",
|
||||
"完全一致",
|
||||
"你怎么还没有被禁赛",
|
||||
"6P41波纹疾走!!!",
|
||||
"牛逼",
|
||||
"草",
|
||||
"草",
|
||||
"cccccccc",
|
||||
"人才不火系列",
|
||||
"双厨狂喜",
|
||||
"双厨曝炸",
|
||||
"火钳留名",
|
||||
"火钳留名",
|
||||
"牛逼啊",
|
||||
"草",
|
||||
"草",
|
||||
"要素过多",
|
||||
"火钳刘明",
|
||||
"高技术力suki",
|
||||
"bo良ki影觉得很赞",
|
||||
"你们的下一句话是名场面",
|
||||
"Niiice",
|
||||
"太草了",
|
||||
"哈哈哈哈",
|
||||
"火钳刘明",
|
||||
"6p41疾走",
|
||||
"袭击妈妈",
|
||||
"占戈哥欠走己",
|
||||
"又看jojo又玩r6的人恐怕太少了吧",
|
||||
"好活当赏",
|
||||
"要素过多",
|
||||
"动作也太流畅了吧",
|
||||
"世界名画",
|
||||
"好活,当赏",
|
||||
"全程高能",
|
||||
"新人都是怪物.jpg",
|
||||
"我的人质啊",
|
||||
"袭击妈妈锁孔看她",
|
||||
"完全不会画画(大嘘)",
|
||||
"好活",
|
||||
"爆头 2333333",
|
||||
"把队友杀了的屑",
|
||||
"动作指导:奥尔加",
|
||||
"草",
|
||||
"要素过多",
|
||||
"噗",
|
||||
"让你玩手机",
|
||||
"6啊",
|
||||
"我负责救人质",
|
||||
"三厨狂喜",
|
||||
"三厨狂喜",
|
||||
"万能日语",
|
||||
"耶———————格——————————",
|
||||
"6P41波纹疾走",
|
||||
"“哦”踩点还行",
|
||||
"火钳刘明。",
|
||||
"哎地唉洗",
|
||||
"这枪不是m249啊,等等叫什么来的",
|
||||
"火钳刘明",
|
||||
"光棍节, 。去过",
|
||||
"炸死队友哈哈哈",
|
||||
"火钳刘明",
|
||||
"火钳刘明",
|
||||
"cao",
|
||||
"火钳刘明",
|
||||
"提前Niiiiiiiice!",
|
||||
"火钳刘明",
|
||||
"神仙UP",
|
||||
"又被爆头了",
|
||||
"6p41疾走",
|
||||
"好活",
|
||||
"人质好好笑啊",
|
||||
"不要停下来啊",
|
||||
"好活啊!!",
|
||||
"6P41波纹疾走 (换成AK是不是更爽)",
|
||||
"恭喜你发现宝藏",
|
||||
"恭喜你发现宝藏",
|
||||
"恭喜你发现宝藏",
|
||||
"前方高能",
|
||||
"封禁30分钟",
|
||||
"火钳刘明",
|
||||
"该赏",
|
||||
"我靠,就冲着高帧数,投币了",
|
||||
"不 要 停 下 来 啊(指你给路)",
|
||||
"卧槽 无情",
|
||||
"草",
|
||||
"ADS草",
|
||||
"世界线收束",
|
||||
"火钳刘明",
|
||||
"人质:给我把抢我跟他拼了",
|
||||
"小车灵魂",
|
||||
"卧槽这帧数",
|
||||
"jojoの奇妙转场",
|
||||
"niiiiiiice",
|
||||
"好活",
|
||||
"要素过多",
|
||||
"6p41",
|
||||
"TK*3移除对战",
|
||||
"这场景布置有弹丸那味儿了",
|
||||
"草",
|
||||
"草",
|
||||
"不要让战斗停下来",
|
||||
"火钳留名",
|
||||
"炸死俩盾哈哈",
|
||||
"太草了,",
|
||||
"万能日语",
|
||||
"伪渲染(确信)",
|
||||
"要素过多",
|
||||
"火钳刘明",
|
||||
"卧槽",
|
||||
"炸死队友",
|
||||
"危",
|
||||
"这才是真正的高技术力",
|
||||
"高技术力suki",
|
||||
"火钳刘明",
|
||||
"欺负我不懂日语系列",
|
||||
"我打我自己",
|
||||
"帧数爆炸",
|
||||
"危",
|
||||
"危",
|
||||
"要素过多",
|
||||
"巨真实这小车",
|
||||
"牛逼",
|
||||
"帧数高的吓人",
|
||||
"5v5→3v3",
|
||||
"我都是俄式救援",
|
||||
"niiiiiiiiiiiice",
|
||||
"别啊!",
|
||||
"尼给路嗒呦",
|
||||
"目测会火",
|
||||
"双厨狂喜",
|
||||
"人质已解救(脱)",
|
||||
"哈哈哈哈哈",
|
||||
"要素过多",
|
||||
"nb",
|
||||
"杀了两个队友不就被踢出去了吗",
|
||||
"这是新人?",
|
||||
"没毛病",
|
||||
"一甲fuze",
|
||||
"要素过多",
|
||||
"大————头————",
|
||||
"人————质————",
|
||||
"这是组长吗?",
|
||||
"不是M249,是PKP",
|
||||
"卡其脱离太",
|
||||
"等等JOJO是你?",
|
||||
"我就是又看JOJO又玩r6",
|
||||
"二乔??????",
|
||||
"这也太流畅了吧",
|
||||
"这tm能出番了这帧数和技术",
|
||||
"kpm波纹疾走",
|
||||
"大制作",
|
||||
"太草了",
|
||||
"耶——格——",
|
||||
"高技术力",
|
||||
"精神小车",
|
||||
"左轮庸医",
|
||||
"袭击人质,锁孔看他",
|
||||
"奈~~斯 屑队友被杀✓",
|
||||
"惨 盾兵 惨",
|
||||
"打敌人误伤不算",
|
||||
"不要停下来啊! (指解救人质)",
|
||||
"嘴巴被贴胶还能说话的人质是鉴",
|
||||
"哈哈哈哈哈哈哈哈哈",
|
||||
"一局11杀",
|
||||
"二乔同款姿势 哈哈",
|
||||
"耶格!",
|
||||
"看",
|
||||
"鉴作无误",
|
||||
"双出狂喜",
|
||||
"为什么不是中文",
|
||||
"经典咚咚咚………三声雷,带你飞",
|
||||
"要素过多",
|
||||
"jojo",
|
||||
"三厨狂喜",
|
||||
"我也是又看又玩",
|
||||
"我都听到lisalisa了doge",
|
||||
"你给路打油",
|
||||
"确实质量很高啊",
|
||||
"NICE",
|
||||
"银魂?",
|
||||
"火钳刘明",
|
||||
"我就是又看jojo又玩R6(1631小时)的,你有什么事吗?",
|
||||
"哟西哟西",
|
||||
"要素过多",
|
||||
"我也是看JOJO,玩r6",
|
||||
"nokk",
|
||||
"800小时r6加二刷jojo在此",
|
||||
"好活",
|
||||
"jojo",
|
||||
"fuze the hostage",
|
||||
"不要停下来!!!!!",
|
||||
"pkppkp波纹疾走",
|
||||
"新人都是怪物吗?",
|
||||
"23333333",
|
||||
"我先来,首页通知书",
|
||||
"咚咚咚放这里。。。",
|
||||
"火钳刘明",
|
||||
"火钳刘明",
|
||||
"火钳刘明",
|
||||
"队友都炸",
|
||||
"nice",
|
||||
"哈哈哈哈",
|
||||
"人质:危!",
|
||||
"危",
|
||||
"火钳刘明",
|
||||
"人质 卒",
|
||||
"你币有了",
|
||||
"打投组",
|
||||
"恭喜首頁通知書!",
|
||||
"要素溢出",
|
||||
"HOSTAGE KIA",
|
||||
"233",
|
||||
"是无托版的PKP",
|
||||
"666",
|
||||
"hostage KIA",
|
||||
"tk哈哈哈",
|
||||
"要素过多",
|
||||
"这个肌肉我可以惹",
|
||||
"6的飞起",
|
||||
"jo风",
|
||||
"混入了奇怪的东西",
|
||||
"草",
|
||||
"袭击妈妈,锁孔看她",
|
||||
"哈哈哈哈哈哈",
|
||||
",",
|
||||
"草",
|
||||
"牛逼",
|
||||
"高技术力啊",
|
||||
"opp",
|
||||
"X",
|
||||
"组长!",
|
||||
"草(中日双语)",
|
||||
"哈哈哈哈哈哈",
|
||||
"-500",
|
||||
".",
|
||||
"看封面识内容系列",
|
||||
"草",
|
||||
"首页通知书",
|
||||
"要素过多",
|
||||
"但是不会画画",
|
||||
"草",
|
||||
"不要停下来啊!",
|
||||
"梅开三度",
|
||||
"四回啊四回",
|
||||
"高帧好评",
|
||||
"人质已解脱",
|
||||
"草",
|
||||
"强",
|
||||
"好活!",
|
||||
"好流畅",
|
||||
"草",
|
||||
"666",
|
||||
"好活儿当赏",
|
||||
"新人都是怪物系列",
|
||||
"高技术力",
|
||||
"niiiiiiiiiiiiiiice",
|
||||
"人质危",
|
||||
"哈哈哈哈",
|
||||
"带制作,三连了",
|
||||
"鉴作",
|
||||
"咚咚咚",
|
||||
"咚咚咚咚棒棒棒棒",
|
||||
"要素过多",
|
||||
"不应该是打中耳机吗",
|
||||
"高技术力",
|
||||
"完了",
|
||||
"彩虹六号牛批",
|
||||
"口罩都有荒木线,佛了",
|
||||
"哈哈哈",
|
||||
"要素爆炸",
|
||||
"高技术力",
|
||||
"cao caocaocaocao",
|
||||
"哈哈哈哈哈哈哈",
|
||||
"等等,2乔这里说的是30分钟",
|
||||
"首页通知书",
|
||||
"海 岸 线",
|
||||
"pkp波纹疾走",
|
||||
"耶————————格————————",
|
||||
"人 质 凶 手 -500",
|
||||
"队友:WDNMD",
|
||||
"jojo???",
|
||||
"点进来之前我以为是fuze饮料。。",
|
||||
"要素过多",
|
||||
"绝了",
|
||||
"要素过多",
|
||||
"灭 霸",
|
||||
"新人都是魔鬼",
|
||||
"帧数爆炸",
|
||||
"Cluster Charge activated!",
|
||||
"要素过多",
|
||||
"Hostage KIA,Mission failed",
|
||||
"人质已解脱。。。",
|
||||
"开 幕 雷 击",
|
||||
"哈哈哈哈",
|
||||
"ADS草死了",
|
||||
"+0",
|
||||
"牛批牛批",
|
||||
"拜见大神",
|
||||
"阿虚",
|
||||
"这帧数,感觉在看动漫",
|
||||
"卡其脱离太",
|
||||
"双厨狂喜",
|
||||
"问问",
|
||||
"不要停下来啊!!!!!",
|
||||
"h",
|
||||
"不要停下来啊",
|
||||
"要真30分钟都不用结束回合了,都开始第二局游戏了",
|
||||
"这也太强了",
|
||||
"。。。。。。。。。。。。",
|
||||
"hoho",
|
||||
"要素过多",
|
||||
"哈哈哈哈哈哈哈哈哈哈哈哈哈哈",
|
||||
"哈哈哈哈哈哈哈哈哈哈",
|
||||
".00",
|
||||
"哈哈",
|
||||
"万能的日语",
|
||||
"首页通知书",
|
||||
"我卡了?",
|
||||
"hhhhh",
|
||||
"大盾闪盾好惨",
|
||||
"哈哈哈哈哈哈哈哈哈",
|
||||
"草",
|
||||
"要素太多受不了哈哈哈哈哈哈哈",
|
||||
"火钳刘明",
|
||||
"首页通知书",
|
||||
"lisalisa",
|
||||
"这是什么蛇皮操作,看不懂",
|
||||
"敌 我 不 分",
|
||||
"草",
|
||||
"666",
|
||||
"哈哈哈哈啊哈哈哈",
|
||||
"完全一致",
|
||||
"要素过多",
|
||||
"你又双叒叕发现了新的宝藏",
|
||||
"火钳刘明",
|
||||
"2333",
|
||||
"高 技 术 力",
|
||||
"三梗合一",
|
||||
"四梗合一",
|
||||
"火钳刘明",
|
||||
"杀2个队友不是直接飞了吗",
|
||||
"首页通知书",
|
||||
"海岸线",
|
||||
"是延迟",
|
||||
"好活当赏",
|
||||
"这个我遇到过,fuze就是我,人质敌人队友都被我杀掉了,被老外骂并被踢了",
|
||||
"草素过多",
|
||||
"人质—— 再不能起",
|
||||
"必须三联",
|
||||
"开始吟唱",
|
||||
"不要停下来啊",
|
||||
"草",
|
||||
"?????????????????",
|
||||
"tab+shift",
|
||||
"帧数高的和动画一样",
|
||||
"wwwwwwwwwwww",
|
||||
"好强",
|
||||
"23333333",
|
||||
"好活当赏",
|
||||
"此曲一出",
|
||||
"要素过载",
|
||||
"火钳刘明",
|
||||
"要素过载",
|
||||
"好活!!!!",
|
||||
"开始吟唱",
|
||||
"我听得懂咋办,在线等,很急",
|
||||
"哇哇哇好高清",
|
||||
".",
|
||||
"医 学 奇 迹",
|
||||
"jo里jo气的",
|
||||
"jojo画风",
|
||||
"哈哈哈哈哈哈",
|
||||
"俄式反恐",
|
||||
"别拦我,老子把3个ADS都丢他脸上",
|
||||
"-500",
|
||||
"万 能 日 语",
|
||||
"666",
|
||||
"人质杀手",
|
||||
"做的真的棒。",
|
||||
"我NM笑疯",
|
||||
"双厨狂喜",
|
||||
"玛撒卡!这是袭击妈妈配音?",
|
||||
"nice",
|
||||
"jojo!",
|
||||
"JO小鬼来力",
|
||||
"真实",
|
||||
"我又玩R6又看JOJO",
|
||||
"完 全 不 会 画 画",
|
||||
"秀儿",
|
||||
"是系统自动踢人的,老外来不及踢你",
|
||||
"6p41波纹疾走",
|
||||
"火钳刘明",
|
||||
"lisalisa?????",
|
||||
"盾——兵——(悲)",
|
||||
"就是没有汤姆逊,汤姆逊波纹疾走!!",
|
||||
"要素过多",
|
||||
"。。。。??",
|
||||
"组长你怎么了组长",
|
||||
"UP:我 完 全 不 会 画 画",
|
||||
"再来亿遍",
|
||||
"泥给路带呦~",
|
||||
"哈哈哈哈哈哈哈哈哈",
|
||||
"哈哈哈哈哈哈哈哈哈",
|
||||
"火钳刘明"
|
||||
];
|
||||
const danmus = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
|
||||
|
||||
const getDanmuData = () => {
|
||||
return danmus.map((text, index) => {
|
||||
|
||||
@@ -8,7 +8,7 @@ defineOptions({
|
||||
name: "Draggable"
|
||||
});
|
||||
|
||||
let gridLists = ref<Array<Object>>([
|
||||
const gridLists = ref<Array<Object>>([
|
||||
{ grid: "cn", num: 1 },
|
||||
{ grid: "cn", num: 2 },
|
||||
{ grid: "cn", num: 3 },
|
||||
@@ -20,14 +20,14 @@ let gridLists = ref<Array<Object>>([
|
||||
{ grid: "cn", num: 9 }
|
||||
]);
|
||||
|
||||
let lists = ref<Array<Object>>([
|
||||
const lists = ref<Array<Object>>([
|
||||
{ people: "cn", id: 1, name: "www.itxst.com" },
|
||||
{ people: "cn", id: 2, name: "www.baidu.com" },
|
||||
{ people: "cn", id: 3, name: "www.taobao.com" },
|
||||
{ people: "cn", id: 4, name: "www.google.com" }
|
||||
]);
|
||||
|
||||
let cutLists = ref([
|
||||
const cutLists = ref([
|
||||
{ people: "cn", id: 1, name: "cut1" },
|
||||
{ people: "cn", id: 2, name: "cut2" },
|
||||
{ people: "cn", id: 3, name: "cut3" },
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, unref } from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import SeamlessScroll from "@/components/ReSeamlessScroll";
|
||||
|
||||
defineOptions({
|
||||
name: "SeamlessScroll"
|
||||
});
|
||||
|
||||
const scroll = templateRef<ElRef | null>("scroll", null);
|
||||
const scroll = ref();
|
||||
|
||||
let listData = ref([
|
||||
const listData = ref([
|
||||
{
|
||||
title: "无缝滚动第一行无缝滚动第一行!!!!!!!!!!"
|
||||
},
|
||||
@@ -39,7 +38,7 @@ let listData = ref([
|
||||
}
|
||||
]);
|
||||
|
||||
let classOption = reactive({
|
||||
const classOption = reactive({
|
||||
direction: "top"
|
||||
});
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ defineOptions({
|
||||
name: "Selector"
|
||||
});
|
||||
|
||||
let selectRange = ref<string>("");
|
||||
let dataLists = ref([
|
||||
const selectRange = ref<string>("");
|
||||
const dataLists = ref([
|
||||
{
|
||||
title: "基本使用",
|
||||
echo: [],
|
||||
@@ -39,7 +39,7 @@ const selectedVal = ({ left, right }): void => {
|
||||
@selectedVal="selectedVal"
|
||||
:disabled="item.disabled"
|
||||
/>
|
||||
<h4 v-if="!item.disabled">选中范围:{{ selectRange }}</h4>
|
||||
<h4 class="mt-3" v-if="!item.disabled">选中范围:{{ selectRange }}</h4>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,10 +15,10 @@ defineOptions({
|
||||
name: "FlowChart"
|
||||
});
|
||||
|
||||
let lf = ref(null);
|
||||
let graphData = ref(null);
|
||||
let dataVisible = ref<boolean>(false);
|
||||
let config = ref({
|
||||
const lf = ref(null);
|
||||
const graphData = ref(null);
|
||||
const dataVisible = ref<boolean>(false);
|
||||
const config = ref({
|
||||
grid: true,
|
||||
background: {
|
||||
color: "#f7f9ff"
|
||||
@@ -27,7 +27,7 @@ let config = ref({
|
||||
enabled: true
|
||||
}
|
||||
});
|
||||
let nodeList = BpmnNode;
|
||||
const nodeList = BpmnNode;
|
||||
|
||||
function initLf() {
|
||||
// 画布配置
|
||||
@@ -94,7 +94,7 @@ onMounted(() => {
|
||||
<div id="LF-Turbo" />
|
||||
<!-- 数据查看面板 -->
|
||||
<el-dialog
|
||||
customClass="flow-dialog"
|
||||
class="flow-dialog"
|
||||
title="数据"
|
||||
v-model="dataVisible"
|
||||
width="50%"
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeMount } from "vue";
|
||||
import { useLoader } from "@pureadmin/utils";
|
||||
import { ElDesignForm } from "vue-form-create2";
|
||||
|
||||
defineOptions({
|
||||
name: "FormDesign"
|
||||
});
|
||||
|
||||
const loading = ref(true);
|
||||
const { loadScript } = useLoader();
|
||||
|
||||
onBeforeMount(() => {
|
||||
loadScript({
|
||||
src: "https://unpkg.com/ace-builds/src-noconflict/ace.js"
|
||||
}).then(message => {
|
||||
if (message === "success") loading.value = false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDesignForm v-loading="loading" style="height: 100vh" class="design-form" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-content {
|
||||
margin: 0 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,62 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import Driver from "driver.js";
|
||||
import "driver.js/dist/driver.min.css";
|
||||
import intro from "intro.js";
|
||||
import "intro.js/minified/introjs.min.css";
|
||||
|
||||
defineOptions({
|
||||
name: "Guide"
|
||||
});
|
||||
|
||||
const steps = [
|
||||
{
|
||||
element: "#header-notice",
|
||||
popover: {
|
||||
title: "消息通知",
|
||||
description: "你可以在这里查看管理员发送的消息",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: "#header-translation",
|
||||
popover: {
|
||||
title: "国际化",
|
||||
description: "你可以在这里进行语言切换",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".set-icon",
|
||||
popover: {
|
||||
title: "项目配置",
|
||||
description: "你可以在这里查看项目配置",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".tags-view",
|
||||
popover: {
|
||||
title: "多标签页",
|
||||
description: "这里是你访问过的页面的历史",
|
||||
position: "buttom"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const driver = new Driver({
|
||||
className: "scoped-class",
|
||||
animate: true,
|
||||
opacity: 0.75,
|
||||
padding: 0,
|
||||
allowClose: true,
|
||||
overlayClickNext: false,
|
||||
doneBtnText: "完成",
|
||||
closeBtnText: "关闭",
|
||||
nextBtnText: "下一步",
|
||||
prevBtnText: "上一步"
|
||||
});
|
||||
|
||||
const guide = () => {
|
||||
driver.defineSteps(steps);
|
||||
driver.start();
|
||||
intro()
|
||||
.setOptions({
|
||||
steps: [
|
||||
{
|
||||
element: document.querySelector("#header-notice"),
|
||||
title: "消息通知",
|
||||
intro: "您可以在这里查看管理员发送的消息",
|
||||
position: "left"
|
||||
},
|
||||
{
|
||||
element: document.querySelector("#header-translation"),
|
||||
title: "国际化",
|
||||
intro: "您可以在这里进行语言切换",
|
||||
position: "left"
|
||||
},
|
||||
{
|
||||
element: document.querySelector(".set-icon"),
|
||||
title: "项目配置",
|
||||
intro: "您可以在这里查看项目配置",
|
||||
position: "left"
|
||||
},
|
||||
{
|
||||
element: document.querySelector(".tags-view"),
|
||||
title: "多标签页",
|
||||
intro: "这里是您访问过的页面的历史",
|
||||
position: "bottom"
|
||||
}
|
||||
]
|
||||
})
|
||||
.start();
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -69,20 +49,8 @@ const guide = () => {
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="margin-top: 10px"
|
||||
@click.prevent.stop="guide"
|
||||
>
|
||||
<el-button type="primary" class="mt-[10px]" @click="guide">
|
||||
打开引导页
|
||||
</el-button>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
div#driver-highlighted-element-stage,
|
||||
div#driver-page-overlay {
|
||||
background: transparent !important;
|
||||
outline: 5000px solid rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -63,11 +63,7 @@ const cardLogoClass = computed(() => [
|
||||
>
|
||||
{{ product.isSetup ? "已启用" : "已停用" }}
|
||||
</el-tag>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
:disabled="!product.isSetup"
|
||||
max-height="2"
|
||||
>
|
||||
<el-dropdown trigger="click" :disabled="!product.isSetup">
|
||||
<IconifyIconOffline icon="more-vertical" class="text-[24px]" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu :disabled="!product.isSetup">
|
||||
|
||||
@@ -62,9 +62,7 @@ function onBack() {
|
||||
clearable
|
||||
v-model="ruleForm.verifyCode"
|
||||
:placeholder="t('login.smsVerifyCode')"
|
||||
:prefix-icon="
|
||||
useRenderIcon('ri:shield-keyhole-line', { online: true })
|
||||
"
|
||||
:prefix-icon="useRenderIcon('ri:shield-keyhole-line')"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="isDisabled"
|
||||
|
||||
@@ -110,9 +110,7 @@ function onBack() {
|
||||
clearable
|
||||
v-model="ruleForm.verifyCode"
|
||||
:placeholder="t('login.smsVerifyCode')"
|
||||
:prefix-icon="
|
||||
useRenderIcon('ri:shield-keyhole-line', { online: true })
|
||||
"
|
||||
:prefix-icon="useRenderIcon('ri:shield-keyhole-line')"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="isDisabled"
|
||||
|
||||
@@ -83,9 +83,7 @@ function onBack() {
|
||||
clearable
|
||||
v-model="ruleForm.verifyCode"
|
||||
:placeholder="t('login.smsVerifyCode')"
|
||||
:prefix-icon="
|
||||
useRenderIcon('ri:shield-keyhole-line', { online: true })
|
||||
"
|
||||
:prefix-icon="useRenderIcon('ri:shield-keyhole-line')"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="isDisabled"
|
||||
|
||||
@@ -67,7 +67,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
useUserStoreHook()
|
||||
.loginByUsername({ username: ruleForm.username })
|
||||
.loginByUsername({ username: ruleForm.username, password: "admin123" })
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
// 获取后端路由
|
||||
@@ -207,9 +207,7 @@ watch(imgCode, value => {
|
||||
clearable
|
||||
v-model="ruleForm.verifyCode"
|
||||
:placeholder="t('login.verifyCode')"
|
||||
:prefix-icon="
|
||||
useRenderIcon('ri:shield-keyhole-line', { online: true })
|
||||
"
|
||||
:prefix-icon="useRenderIcon('ri:shield-keyhole-line')"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<ReImageVerify v-model:code="imgCode" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FormInstance, FormItemProp } from "element-plus";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { clone } from "@pureadmin/utils";
|
||||
import { ref } from "vue";
|
||||
|
||||
const isDisabled = ref(false);
|
||||
@@ -13,7 +13,7 @@ export const useVerifyCode = () => {
|
||||
time = 60
|
||||
) => {
|
||||
if (!formEl) return;
|
||||
const initTime = cloneDeep(time);
|
||||
const initTime = clone(time, true);
|
||||
await formEl.validateField(props, isValid => {
|
||||
if (isValid) {
|
||||
clearInterval(timer.value);
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "Menu1-1"
|
||||
});
|
||||
|
||||
let input = ref("");
|
||||
const input = ref("");
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "Menu1-2-1"
|
||||
});
|
||||
|
||||
let input = ref("");
|
||||
const input = ref("");
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user