mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-03 13:44:47 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -1,8 +1,8 @@
|
||||
# 项目本地运行端口号
|
||||
# 平台本地运行端口号
|
||||
VITE_PORT = 8848
|
||||
|
||||
# 开发环境读取配置文件路径
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 开发环境路由历史模式
|
||||
# 开发环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
# 线上环境项目打包路径
|
||||
# 线上环境平台打包路径
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 线上环境路由历史模式
|
||||
# 线上环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
|
||||
VITE_LEGACY = false
|
||||
|
||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||
VITE_CDN = false
|
||||
|
||||
|
||||
@@ -4,12 +4,9 @@ NODE_ENV=production
|
||||
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# 线上环境路由历史模式
|
||||
# 预发布环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
|
||||
VITE_ROUTER_HISTORY = "hash"
|
||||
|
||||
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
|
||||
VITE_LEGACY = false
|
||||
|
||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||
VITE_CDN = true
|
||||
|
||||
|
||||
@@ -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,27 @@
|
||||
# 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
|
||||
@@ -121,7 +145,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
|
||||
@@ -282,7 +306,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)
|
||||
|
||||
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,3 +1,27 @@
|
||||
# 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
|
||||
@@ -121,7 +145,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
|
||||
@@ -282,7 +306,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,27 @@
|
||||
# 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
|
||||
@@ -83,7 +107,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
|
||||
|
||||
@@ -121,7 +145,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)
|
||||
- 添加登录页国际化
|
||||
@@ -282,7 +306,6 @@
|
||||
- 优化标签页,带来更好的交互体验
|
||||
- 路由 title 支持直接写中文,可脱离国际化
|
||||
- 路由历史模式从 env 读取并支持 base 参数
|
||||
- 打包后的文件提供传统浏览器兼容性支持,配置 VITE_LEGACY 为 true
|
||||
|
||||
# 2.6.0(2021-11-10)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## 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 (support `PWA` fast, offline access)
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
- [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](https://yiming_chang.gitee.io/vue-pure-admin)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## 配套视频
|
||||
|
||||
- [点我查看教程](https://www.bilibili.com/video/BV1534y1S7HV)
|
||||
- [点我查看快速开发教程](https://www.bilibili.com/video/BV1kg411v7QT)
|
||||
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
|
||||
|
||||
## 配套文档(支持 `PWA` 快速、离线访问)
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
- [点我查看 Tauri 版](https://github.com/xiaoxian521/tauri-pure-admin)
|
||||
|
||||
## Electron 版
|
||||
|
||||
- [点我查看 Electron 版](https://github.com/xiaoxian521/electron-pure-admin)
|
||||
|
||||
## 预览
|
||||
|
||||
- [点我查看国内预览站](https://yiming_chang.gitee.io/vue-pure-admin)
|
||||
@@ -144,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,11 +1,10 @@
|
||||
/** 处理环境变量 */
|
||||
const warpperEnv = (envConf: Recordable): ViteEnv => {
|
||||
/** 此处为默认值,无需修改 */
|
||||
/** 此处为默认值 */
|
||||
const ret: ViteEnv = {
|
||||
VITE_PORT: 8848,
|
||||
VITE_PUBLIC_PATH: "",
|
||||
VITE_ROUTER_HISTORY: "",
|
||||
VITE_LEGACY: false,
|
||||
VITE_CDN: false,
|
||||
VITE_COMPRESSION: "none"
|
||||
};
|
||||
@@ -28,7 +27,7 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
|
||||
return ret;
|
||||
};
|
||||
|
||||
/** 环境变量 */
|
||||
/** 获取环境变量 */
|
||||
const loadEnv = (): ViteEnv => {
|
||||
return import.meta.env;
|
||||
};
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
68
package.json
68
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-pure-admin",
|
||||
"version": "3.6.4",
|
||||
"version": "3.7.0",
|
||||
"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",
|
||||
@@ -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,33 +94,33 @@
|
||||
"@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",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/runtime-core": "^3.2.45",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"cloc": "^2.10.0",
|
||||
"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",
|
||||
@@ -135,26 +133,26 @@
|
||||
"pretty-quick": "3.1.1",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup-plugin-visualizer": "^5.8.3",
|
||||
"sass": "^1.53.0",
|
||||
"sass-loader": "^13.0.2",
|
||||
"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.2",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"terser": "^5.15.1",
|
||||
"typescript": "^4.7.4",
|
||||
"unplugin-vue-define-options": "0.7.3",
|
||||
"vite": "^3.1.8",
|
||||
"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.2.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": {
|
||||
|
||||
2442
pnpm-lock.yaml
generated
2442
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"Version": "3.6.4",
|
||||
"Version": "3.7.0",
|
||||
"Title": "PureAdmin",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
@@ -16,6 +16,7 @@
|
||||
"EpThemeColor": "#409EFF",
|
||||
"ShowLogo": true,
|
||||
"ShowModel": "smart",
|
||||
"MenuArrowIconNoTransition": false,
|
||||
"MapConfigure": {
|
||||
"amapKey": "97b3248d1553172e81f168cf94ea667e",
|
||||
"options": {
|
||||
|
||||
@@ -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"
|
||||
});
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,13 @@
|
||||
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[2].key);
|
||||
const notices = ref(noticesData);
|
||||
|
||||
let noticesNum = ref(0);
|
||||
const noticesNum = ref(0);
|
||||
notices.value.forEach(notice => {
|
||||
noticesNum.value += notice.list.length;
|
||||
});
|
||||
@@ -33,7 +32,8 @@ function tabClick() {
|
||||
<Tabs
|
||||
centered
|
||||
class="dropdown-tabs"
|
||||
v-model:activeName="activeName"
|
||||
:tabBarStyle="{ marginLeft: notices?.length > 4 ? '8px' : '0' }"
|
||||
v-model="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";
|
||||
|
||||
@@ -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 隐藏侧边栏
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 });
|
||||
```
|
||||
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";
|
||||
|
||||
/**
|
||||
* 简版前端单点登录,根据实际业务自行编写
|
||||
* 划重点:
|
||||
* 判断是否为单点登录,不为则直接返回不再进行任何逻辑处理,下面是单点登录后的逻辑处理
|
||||
* 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();
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
defineOptions({
|
||||
name: "Menu1-2-2"
|
||||
});
|
||||
|
||||
let input = ref("");
|
||||
const input = ref("");
|
||||
const { t } = useI18n();
|
||||
const { query } = useRoute();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -16,5 +18,9 @@ const { t } = useI18n();
|
||||
<p style="text-indent: 2em">{{ t("menus.hsmenu1-2") }}</p>
|
||||
<p style="text-indent: 4em">{{ t("menus.hsmenu1-2-2") }}</p>
|
||||
<el-input v-model="input" />
|
||||
|
||||
<div class="mt-4" v-if="query.text">
|
||||
此页面携带的参数值为:{{ query.text }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "Menu1-3"
|
||||
});
|
||||
|
||||
let input = ref("");
|
||||
const input = ref("");
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "Menu2"
|
||||
});
|
||||
|
||||
let input = ref("");
|
||||
const input = ref("");
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: "PermissionButton"
|
||||
});
|
||||
|
||||
let elStyle = computed((): CSSProperties => {
|
||||
const elStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: "85vw",
|
||||
justifyContent: "start"
|
||||
|
||||
@@ -8,14 +8,14 @@ defineOptions({
|
||||
name: "PermissionPage"
|
||||
});
|
||||
|
||||
let elStyle = computed((): CSSProperties => {
|
||||
const elStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: "85vw",
|
||||
justifyContent: "start"
|
||||
};
|
||||
});
|
||||
|
||||
let username = ref(useUserStoreHook()?.username);
|
||||
const username = ref(useUserStoreHook()?.username);
|
||||
|
||||
const options = [
|
||||
{
|
||||
|
||||
22
src/views/pure-table/components/base.vue
Normal file
22
src/views/pure-table/components/base.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { tableData } from "./data";
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="tableData" :columns="columns" />
|
||||
</template>
|
||||
22
src/views/pure-table/components/border.vue
Normal file
22
src/views/pure-table/components/border.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { tableData } from "./data";
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="tableData" :columns="columns" border />
|
||||
</template>
|
||||
70
src/views/pure-table/components/column-template/columns.tsx
Normal file
70
src/views/pure-table/components/column-template/columns.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { message } from "@pureadmin/components";
|
||||
import { tableData } from "../data";
|
||||
|
||||
// 如果您不习惯tsx写法,可以传slot,然后在template里写
|
||||
// 需是hooks写法(函数中有return),避免失去响应性
|
||||
export function useColumns() {
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date",
|
||||
cellRenderer: ({ row }) => (
|
||||
<div style="display: flex; align-items: center">
|
||||
<iconify-icon-online icon="ep:timer" />
|
||||
<span style="margin-left: 10px">{row.date}</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name",
|
||||
cellRenderer: ({ row }) => (
|
||||
<el-popover effect="light" trigger="hover" placement="top" width="auto">
|
||||
{{
|
||||
default: () => (
|
||||
<>
|
||||
<div>name: {row.name}</div>
|
||||
<div>address: {row.address}</div>
|
||||
</>
|
||||
),
|
||||
reference: () => <el-tag>{row.name}</el-tag>
|
||||
}}
|
||||
</el-popover>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
cellRenderer: ({ index, row }) => (
|
||||
<>
|
||||
<el-button size="small" onClick={() => handleEdit(index + 1, row)}>
|
||||
Edit
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
onClick={() => handleDelete(index + 1, row)}
|
||||
>
|
||||
Delete
|
||||
</el-button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
const handleEdit = (index: number, row) => {
|
||||
message.success(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`);
|
||||
};
|
||||
|
||||
const handleDelete = (index: number, row) => {
|
||||
message.error(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`);
|
||||
};
|
||||
|
||||
return {
|
||||
columns,
|
||||
tableData
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { useColumns } from "./columns";
|
||||
|
||||
const { columns, tableData } = useColumns();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="tableData" :columns="columns" />
|
||||
</template>
|
||||
30
src/views/pure-table/components/customIndex.vue
Normal file
30
src/views/pure-table/components/customIndex.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import { tableData } from "./data";
|
||||
|
||||
const indexMethod = (index: number) => {
|
||||
return index * 2;
|
||||
};
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
type: "index",
|
||||
index: indexMethod
|
||||
},
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="tableData" :columns="columns" />
|
||||
</template>
|
||||
285
src/views/pure-table/components/data.ts
Normal file
285
src/views/pure-table/components/data.ts
Normal file
@@ -0,0 +1,285 @@
|
||||
import dayjs from "dayjs";
|
||||
import { clone } from "@pureadmin/utils";
|
||||
|
||||
const date = dayjs(new Date()).format("YYYY-MM-DD");
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
date,
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Jack",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Dick",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Harry",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Sam",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Lucy",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Mary",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
},
|
||||
{
|
||||
date,
|
||||
name: "Mike",
|
||||
address: "No. 189, Grove St, Los Angeles"
|
||||
}
|
||||
];
|
||||
|
||||
const cloneData = clone(tableData, true);
|
||||
|
||||
const tableDataMore = cloneData.map(item =>
|
||||
Object.assign(item, {
|
||||
state: "California",
|
||||
city: "Los Angeles",
|
||||
"post-code": "CA 90036"
|
||||
})
|
||||
);
|
||||
|
||||
const tableDataSortable = cloneData.map((item, index) =>
|
||||
Object.assign(item, {
|
||||
date: `${dayjs(new Date()).format("YYYY-MM")}-${index + 1}`
|
||||
})
|
||||
);
|
||||
|
||||
const tableDataExpand = [
|
||||
{
|
||||
date: "2016-05-03",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-02",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-04",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-01",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-08",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-06",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2016-05-07",
|
||||
name: "Tom",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114",
|
||||
family: [
|
||||
{
|
||||
name: "Jerry",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Spike",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
},
|
||||
{
|
||||
name: "Tyke",
|
||||
state: "California",
|
||||
city: "San Francisco",
|
||||
address: "3650 21st St, San Francisco",
|
||||
zip: "CA 94114"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export { tableData, tableDataMore, tableDataSortable, tableDataExpand };
|
||||
72
src/views/pure-table/components/expand.vue
Normal file
72
src/views/pure-table/components/expand.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { tableDataExpand } from "./data";
|
||||
|
||||
const parentBorder = ref(false);
|
||||
const childBorder = ref(false);
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
type: "expand",
|
||||
slot: "expand"
|
||||
},
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
}
|
||||
];
|
||||
|
||||
const childColumns: TableColumnList = [
|
||||
{
|
||||
label: "Name",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "State",
|
||||
prop: "state"
|
||||
},
|
||||
{
|
||||
label: "City",
|
||||
prop: "city"
|
||||
},
|
||||
{
|
||||
label: "Address",
|
||||
prop: "address"
|
||||
},
|
||||
{
|
||||
label: "Zip",
|
||||
prop: "zip"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
switch parent border: <el-switch v-model="parentBorder" /> switch child
|
||||
border: <el-switch v-model="childBorder" />
|
||||
<pure-table
|
||||
:data="tableDataExpand"
|
||||
:columns="columns"
|
||||
:border="parentBorder"
|
||||
>
|
||||
<template #expand="{ row }">
|
||||
<div class="m-4">
|
||||
<p class="mb-2">State: {{ row.state }}</p>
|
||||
<p class="mb-2">City: {{ row.city }}</p>
|
||||
<p class="mb-2">Address: {{ row.address }}</p>
|
||||
<p class="mb-4">Zip: {{ row.zip }}</p>
|
||||
<h3>Family</h3>
|
||||
<pure-table
|
||||
:data="row.family"
|
||||
:columns="childColumns"
|
||||
:border="childBorder"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</pure-table>
|
||||
</div>
|
||||
</template>
|
||||
104
src/views/pure-table/components/filters.vue
Normal file
104
src/views/pure-table/components/filters.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
const tableRef = ref();
|
||||
|
||||
const clearFilter = val => {
|
||||
const { clearFilter } = tableRef.value.getTableRef();
|
||||
clearFilter(val);
|
||||
};
|
||||
|
||||
const resetDateFilter = () => {
|
||||
clearFilter(["date"]);
|
||||
};
|
||||
|
||||
const filterTag = (value, row) => {
|
||||
return row.tag === value;
|
||||
};
|
||||
|
||||
const filterHandler = (value, row, column) => {
|
||||
const property = column["property"];
|
||||
return row[property] === value;
|
||||
};
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date",
|
||||
sortable: true,
|
||||
columnKey: "date",
|
||||
filters: [
|
||||
{ text: "2016-05-01", value: "2016-05-01" },
|
||||
{ text: "2016-05-02", value: "2016-05-02" },
|
||||
{ text: "2016-05-03", value: "2016-05-03" },
|
||||
{ text: "2016-05-04", value: "2016-05-04" }
|
||||
],
|
||||
filterMethod: filterHandler
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
},
|
||||
{
|
||||
label: "标签",
|
||||
prop: "tag",
|
||||
filters: [
|
||||
{ text: "Home", value: "Home" },
|
||||
{ text: "Office", value: "Office" }
|
||||
],
|
||||
filterMethod: filterTag,
|
||||
filterPlacement: "bottom-end",
|
||||
slot: "tag"
|
||||
}
|
||||
];
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
date: "2016-05-03",
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles",
|
||||
tag: "Home"
|
||||
},
|
||||
{
|
||||
date: "2016-05-02",
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles",
|
||||
tag: "Office"
|
||||
},
|
||||
{
|
||||
date: "2016-05-04",
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles",
|
||||
tag: "Home"
|
||||
},
|
||||
{
|
||||
date: "2016-05-01",
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles",
|
||||
tag: "Office"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="resetDateFilter">reset date filter</el-button>
|
||||
<el-button @click="clearFilter">reset all filters</el-button>
|
||||
<pure-table
|
||||
ref="tableRef"
|
||||
row-key="date"
|
||||
:data="tableData"
|
||||
:columns="columns"
|
||||
>
|
||||
<template #tag="{ row }">
|
||||
<el-tag :type="row.tag === 'Home' ? '' : 'success'" disable-transitions>
|
||||
{{ row.tag }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</pure-table>
|
||||
</div>
|
||||
</template>
|
||||
79
src/views/pure-table/components/fixColumn.vue
Normal file
79
src/views/pure-table/components/fixColumn.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { tableDataMore } from "./data";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
height?: string;
|
||||
}>(),
|
||||
{
|
||||
height: null
|
||||
}
|
||||
);
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date",
|
||||
width: "260",
|
||||
fixed: true
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "地区",
|
||||
prop: "state",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "城市",
|
||||
prop: "city",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "邮编",
|
||||
prop: "post-code",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
width: "120",
|
||||
fixed: "right",
|
||||
slot: "operation"
|
||||
}
|
||||
];
|
||||
|
||||
function handleClick(row) {
|
||||
console.log(
|
||||
"%crow===>>>: ",
|
||||
"color: MidnightBlue; background: Aquamarine; font-size: 20px;",
|
||||
row
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table
|
||||
:data="
|
||||
props.height
|
||||
? tableDataMore.concat(tableDataMore).concat(tableDataMore)
|
||||
: tableDataMore
|
||||
"
|
||||
:columns="columns"
|
||||
:height="props.height"
|
||||
>
|
||||
<template #operation="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleClick(row)">
|
||||
Detail
|
||||
</el-button>
|
||||
<el-button link type="primary" size="small">Edit</el-button>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
26
src/views/pure-table/components/fixHeader.vue
Normal file
26
src/views/pure-table/components/fixHeader.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { tableData } from "./data";
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table
|
||||
:data="tableData.concat(tableData).concat(tableData)"
|
||||
:columns="columns"
|
||||
height="360"
|
||||
/>
|
||||
</template>
|
||||
84
src/views/pure-table/components/fluidHeight.vue
Normal file
84
src/views/pure-table/components/fluidHeight.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import { tableDataMore } from "./data";
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date",
|
||||
width: "260",
|
||||
fixed: true
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "地区",
|
||||
prop: "state",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "城市",
|
||||
prop: "city",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "邮编",
|
||||
prop: "post-code",
|
||||
width: "260"
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
width: "120",
|
||||
fixed: "right",
|
||||
slot: "operation"
|
||||
}
|
||||
];
|
||||
|
||||
const now = new Date();
|
||||
const tableData = ref(tableDataMore);
|
||||
|
||||
const deleteRow = (index: number) => {
|
||||
tableData.value.splice(index, 1);
|
||||
};
|
||||
|
||||
const onAddItem = () => {
|
||||
now.setDate(now.getDate() + 1);
|
||||
tableData.value.push({
|
||||
date: dayjs(now).format("YYYY-MM-DD"),
|
||||
name: "Tom",
|
||||
address: "No. 189, Grove St, Los Angeles",
|
||||
state: "California",
|
||||
city: "Los Angeles",
|
||||
"post-code": "CA 90036"
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<pure-table :data="tableData" :columns="columns" maxHeight="500">
|
||||
<template #operation="{ $index }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click.prevent="deleteRow($index)"
|
||||
>
|
||||
Remove
|
||||
</el-button>
|
||||
</template>
|
||||
</pure-table>
|
||||
<el-button class="mt-4" style="width: 100%" @click="onAddItem">
|
||||
Add Item
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
38
src/views/pure-table/components/groupHeader.vue
Normal file
38
src/views/pure-table/components/groupHeader.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { tableDataMore } from "./data";
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date",
|
||||
fixed: true
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name",
|
||||
children: [
|
||||
{
|
||||
label: "地区",
|
||||
children: [
|
||||
{
|
||||
label: "城市",
|
||||
prop: "city"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "邮编",
|
||||
prop: "post-code"
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="tableDataMore" :columns="columns" alignWhole="center" />
|
||||
</template>
|
||||
70
src/views/pure-table/components/header-renderer/columns.tsx
Normal file
70
src/views/pure-table/components/header-renderer/columns.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { message } from "@pureadmin/components";
|
||||
import { tableData } from "../data";
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
// 如果您不习惯tsx写法,可以传slot,然后在template里写
|
||||
// 需是hooks写法(函数中有return),避免失去响应性
|
||||
export function useColumns() {
|
||||
const search = ref("");
|
||||
const filterTableData = computed(() =>
|
||||
tableData.filter(
|
||||
data =>
|
||||
!search.value ||
|
||||
data.name.toLowerCase().includes(search.value.toLowerCase())
|
||||
)
|
||||
);
|
||||
|
||||
const handleEdit = (index: number, row) => {
|
||||
message.success(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`);
|
||||
};
|
||||
|
||||
const handleDelete = (index: number, row) => {
|
||||
message.error(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`);
|
||||
};
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
label: "日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "姓名",
|
||||
prop: "name"
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
prop: "address"
|
||||
},
|
||||
{
|
||||
align: "right",
|
||||
// 自定义表头
|
||||
headerRenderer: () => (
|
||||
<el-input
|
||||
v-model={search.value}
|
||||
size="small"
|
||||
clearable
|
||||
placeholder="Type to search"
|
||||
/>
|
||||
),
|
||||
cellRenderer: ({ index, row }) => (
|
||||
<>
|
||||
<el-button size="small" onClick={() => handleEdit(index + 1, row)}>
|
||||
Edit
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
onClick={() => handleDelete(index + 1, row)}
|
||||
>
|
||||
Delete
|
||||
</el-button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
columns,
|
||||
filterTableData
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { useColumns } from "./columns";
|
||||
|
||||
const { columns, filterTableData } = useColumns();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table :data="filterTableData" :columns="columns" />
|
||||
</template>
|
||||
43
src/views/pure-table/components/index.ts
Normal file
43
src/views/pure-table/components/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import Base from "./base.vue";
|
||||
import Stripe from "./stripe.vue";
|
||||
import Border from "./border.vue";
|
||||
import Status from "./status.vue";
|
||||
import FixHeader from "./fixHeader.vue";
|
||||
import FixColumn from "./fixColumn.vue";
|
||||
import FluidHeight from "./fluidHeight.vue";
|
||||
import GroupHeader from "./groupHeader.vue";
|
||||
import Radio from "./radio.vue";
|
||||
import MultipleChoice from "./multipleChoice.vue";
|
||||
import Sortable from "./sortable.vue";
|
||||
import Filters from "./filters.vue";
|
||||
import ColumnTemplate from "./column-template/index.vue";
|
||||
import HeaderRenderer from "./header-renderer/index.vue";
|
||||
import Expand from "./expand.vue";
|
||||
import TreeTable from "./tree.vue";
|
||||
import TotalRow from "./totalRow.vue";
|
||||
import Merge from "./merge.vue";
|
||||
import CustomIndex from "./customIndex.vue";
|
||||
import Layout from "./layout.vue";
|
||||
|
||||
export {
|
||||
Base,
|
||||
Stripe,
|
||||
Border,
|
||||
Status,
|
||||
FixHeader,
|
||||
FixColumn,
|
||||
FluidHeight,
|
||||
GroupHeader,
|
||||
Radio,
|
||||
MultipleChoice,
|
||||
Sortable,
|
||||
Filters,
|
||||
ColumnTemplate,
|
||||
HeaderRenderer,
|
||||
Expand,
|
||||
TreeTable,
|
||||
TotalRow,
|
||||
Merge,
|
||||
CustomIndex,
|
||||
Layout
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user