mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-11-30 14:32:23 +08:00
version: v5.2.4
This commit is contained in:
parent
bebd3d53bd
commit
d1cedda1f7
62
.cursorrules
Normal file
62
.cursorrules
Normal file
@ -0,0 +1,62 @@
|
||||
# Role
|
||||
你是一名精通Vue.js的高级全栈工程师,拥有20年的Web开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Vue.js项目的开发。你的工作对用户来说非常重要,完成后将获得10000美元奖励。
|
||||
|
||||
# Goal
|
||||
你的目标是以用户容易理解的方式帮助他们完成Vue.js项目的设计和开发工作。你应该主动完成所有工作,而不是等待用户多次推动你。
|
||||
|
||||
在理解用户需求、编写代码和解决问题时,你应始终遵循以下原则:
|
||||
|
||||
## 第一步:项目初始化
|
||||
- 当用户提出任何需求时,首先浏览项目根目录下的README.md文件和所有代码文档,理解项目目标、架构和实现方式。
|
||||
- 如果还没有README文件,创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。
|
||||
- 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明,确保用户可以轻松理解和使用这些功能。
|
||||
|
||||
# 本规则由 AI进化论-花生 创建,版权所有,引用请注明出处
|
||||
|
||||
## 第二步:需求分析和开发
|
||||
### 理解用户需求时:
|
||||
- 充分理解用户需求,站在用户角度思考。
|
||||
- 作为产品经理,分析需求是否存在缺漏,与用户讨论并完善需求。
|
||||
- 选择最简单的解决方案来满足用户需求。
|
||||
|
||||
### 编写代码时:
|
||||
- 在.vue文件中使用Vue 3的Composition API进行开发,合理使用setup语法糖。
|
||||
- 在.tsx文件中使用Vue3的TSX语法进行开发,合理使用defineComponent、ref、reactive等响应式API。
|
||||
- 遵循Vue.js的最佳实践和设计模式,如单文件组件(SFC)。
|
||||
- 利用Vue Router进行路由管理,实现页面导航和路由守卫。
|
||||
- 使用Pinia进行状态管理,合理组织store结构。
|
||||
- 实现组件化开发,确保组件的可复用性和可维护性。
|
||||
- 使用Vue的响应式系统,合理使用ref、reactive等响应式API。
|
||||
- 实现响应式设计,确保在不同设备上的良好体验。
|
||||
- 使用TypeScript进行类型检查,提高代码质量。
|
||||
- 编写详细的代码注释,并在代码中添加必要的错误处理和日志记录。
|
||||
- 合理使用Vue的生命周期钩子和组合式函数。
|
||||
- 如果涉及到可视化需求,使用echarts进行图表的绘制,并且优先使用v6版本配置方式。
|
||||
- 使用naive-ui进行UI组件的开发,合理使用naive-ui的组件。
|
||||
|
||||
整个过程中参考如下的文档:
|
||||
- [jsx/tsx 文档](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx#readme)
|
||||
- [echarts 文档](https://echarts.apache.org/zh/option.html)
|
||||
- [naive-ui 文档](https://www.naiveui.com/zh-CN/os-theme/docs/introduction)
|
||||
- [naive-ui 组件](https://www.naiveui.com/zh-CN/os-theme/components)
|
||||
|
||||
### 解决问题时:
|
||||
- 全面阅读相关代码文件,理解所有代码的功能和逻辑。
|
||||
- 分析导致错误的原因,提出解决问题的思路。
|
||||
- 与用户进行多次交互,根据反馈调整解决方案。
|
||||
- 善用Vue DevTools进行调试和性能分析。
|
||||
- 当一个bug经过两次调整仍未解决时,你将启动系统二思考模式:
|
||||
1. 系统性分析bug产生的根本原因
|
||||
2. 提出可能的假设
|
||||
3. 设计验证假设的方法
|
||||
4. 提供三种不同的解决方案,并详细说明每种方案的优缺点
|
||||
5. 让用户根据实际情况选择最适合的方案
|
||||
|
||||
## 第三步:项目总结和优化
|
||||
- 完成任务后,反思完成步骤,思考项目可能存在的问题和改进方式。
|
||||
- 更新README.md文件,包括新增功能说明和优化建议。
|
||||
- 考虑使用Vue的高级特性,如Suspense、Teleport等来增强功能。
|
||||
- 优化应用性能,包括代码分割、懒加载、虚拟列表等。
|
||||
- 实现适当的错误边界处理和性能监控。
|
||||
|
||||
在整个过程中,始终参考[Vue.js官方文档](https://vuejs.org/guide/introduction.html),确保使用最新的Vue.js开发最佳实践。
|
||||
@ -17,4 +17,5 @@ module.exports = {
|
||||
htmlWhitespaceSensitivity: 'css', // 根据显示样式决定 `html` 要不要折行
|
||||
endOfLine: 'lf', // 换行符使用 `lf`,
|
||||
singleAttributePerLine: false,
|
||||
bracketSameLine: false,
|
||||
}
|
||||
|
||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@ -1,3 +1,3 @@
|
||||
{
|
||||
"recommendations": ["vue.volar", "lokalise.i18n-ally"]
|
||||
"recommendations": ["lokalise.i18n-ally"]
|
||||
}
|
||||
|
||||
33
.vscode/settings.json
vendored
33
.vscode/settings.json
vendored
@ -1,5 +1,38 @@
|
||||
{
|
||||
// 格式化配置
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
// 按文件类型指定格式化工具
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sortKeys": true,
|
||||
|
||||
44
CHANGELOG.md
44
CHANGELOG.md
@ -1,3 +1,45 @@
|
||||
## 5.2.4
|
||||
|
||||
## Feats
|
||||
|
||||
- 新增 `.cursorrules` 文件,用于配置 `cursor` 的规则
|
||||
- `RChart` 组件相关
|
||||
- 新增 `watchDeep` 配置项,允许配置是否深度监听 `options` 配置项,在某些场景下不希望监听 `options` 配置项的变动时,可以配置该项为 `false`
|
||||
- 修改自定义样式名,由 `--r` 前缀改为 `--r` 前缀
|
||||
- 优化 `RTable`, `RTablePro` 组件与相关 `hook`
|
||||
- 移除未使用的导入(`DataTableInst`、`ExtractPublicPropTypes`、`emit`)
|
||||
- 将 `contextMenuSelect` 中的状态更新提前
|
||||
- 提取 `handleContextMenu` 函数,避免重复创建
|
||||
- 优化 `combineRowProps` 的条件判断
|
||||
- 提取 `renderDefaultToolOptions` 为独立函数
|
||||
- 简化 `tool` 函数的条件判断
|
||||
- 移除不必要的 `.bind(this)` 调用
|
||||
- 如果未启用 `onUpdateColumns` 或 `onUpdate:columns` 事件(也就是双向绑定 `columns` 配置项),则认为不需要渲染 `C` 组件,因为有时候你可能希望 `columns` 配置项可能就是写死的,不需要动态修改
|
||||
- 使用 `nextTick` 优化列配置更新(`C` 组件)
|
||||
- 减少函数重复创建
|
||||
- 优化条件判断逻辑
|
||||
- `selectKeys(keys: RowKey[])` - 批量选中
|
||||
- `toggleKey(key: RowKey)` - 切换选中状态
|
||||
- `isKeySelected(key: RowKey)` - 检查是否选中
|
||||
- 新增 `autoDeleteDuplicateKeys` 配置项,允许自定义是否移除重复请求 `key`
|
||||
- `usePagination` 方法相关
|
||||
- 修改 `getCallback` 方法返回值类型,现在会自动推导回调函数类型(仅在默认传递回调函数时有效)
|
||||
- 修改 `getCallback` 方法使用方式,改为函数调用
|
||||
- `RBarcode` 组件相关
|
||||
- 新增 `responsive` 配置项,允许配置是否启用响应式尺寸,当容器大小变化时自动重新渲染条形码,但是该属性让 `width` 与 `height` 配置项失效
|
||||
- 新增 `.vscode` 配置规则,默认强制使用 `prettier` 格式化代码,并且使用 `eslint` 检查代码规范
|
||||
- 移除所有 `--ray` 的前缀为 `-r`
|
||||
- 统一自定义组件的文件分包格式
|
||||
- 标记自定义 `useModal` 方法为遗弃方法
|
||||
- `useAxiosInterceptor` 更名为 `axiosInterceptor` 方法,旧方法名不符合语义化,现在更加语义化
|
||||
- 优化 `useElementFullscreen` 方法
|
||||
- 调整 `MenuTag` 组件样式,现在会根据主题色自动适配关闭按钮颜色
|
||||
|
||||
## Fixes
|
||||
|
||||
- 修复 `useTablePro.print` 方法无效的问题
|
||||
- 修复 `vitest` 插件启动会提示失败的问题
|
||||
|
||||
## 5.2.3
|
||||
|
||||
## Feats
|
||||
@ -2258,7 +2300,7 @@ useAppTheme key 类型: 'dark' | 'light'
|
||||
### Feats
|
||||
|
||||
- 修改 Menu 菜单过滤逻辑,现在如果权限不匹配或者设置了 hidden 属性,则会被过滤掉
|
||||
- 移除 $activedColor 全局 sass 变量,使用 --ray-theme-primary-color 替代
|
||||
- 移除 $activedColor 全局 sass 变量,使用 --r-theme-primary-color 替代
|
||||
- 新增路由菜单检索功能
|
||||
- 移除 App.tsx 中同步主题方法,改为使用 cfg 配置并且使用 ejs 注入
|
||||
- 移除 MenuTag 默认主题色,现在会以当前主题色为主色
|
||||
|
||||
@ -91,7 +91,7 @@ export default [
|
||||
ignoreRestArgs: true,
|
||||
},
|
||||
],
|
||||
'prettier/prettier': 'error',
|
||||
'prettier/prettier': ['error', {}],
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
:root {
|
||||
--preloading-tag-color: <%= preloadingConfig.tagColor %>;
|
||||
--preloading-title-color: <%= preloadingConfig.titleColor %>;
|
||||
--ray-theme-primary-fade-color: <%= appPrimaryColor.primaryFadeColor %>;
|
||||
--ray-theme-primary-color: <%= appPrimaryColor.primaryColor %>;
|
||||
--r-theme-primary-fade-color: <%= appPrimaryColor.primaryFadeColor %>;
|
||||
--r-theme-primary-color: <%= appPrimaryColor.primaryColor %>;
|
||||
--global-loading-bg-color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ray-template",
|
||||
"private": false,
|
||||
"version": "5.2.3",
|
||||
"version": "5.2.4",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||
@ -51,7 +51,7 @@
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.4.1",
|
||||
"print-js": "^1.6.0",
|
||||
"vue": "^3.5.22",
|
||||
"vue": "^3.5.24",
|
||||
"vue-demi": "0.14.10",
|
||||
"vue-hooks-plus": "2.4.1",
|
||||
"vue-i18n": "^9.13.1",
|
||||
@ -80,8 +80,8 @@
|
||||
"autoprefixer": "10.4.21",
|
||||
"depcheck": "1.4.7",
|
||||
"eslint": "9.31.0",
|
||||
"eslint-config-prettier": "10.1.5",
|
||||
"eslint-plugin-prettier": "5.5.1",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-prettier": "5.5.4",
|
||||
"eslint-plugin-vue": "9.32.0",
|
||||
"globals": "16.3.0",
|
||||
"happy-dom": "17.1.0",
|
||||
|
||||
303
pnpm-lock.yaml
generated
303
pnpm-lock.yaml
generated
@ -16,7 +16,7 @@ importers:
|
||||
version: 2.0.14(@logicflow/core@2.0.10)
|
||||
'@vueuse/core':
|
||||
specifier: ^13.1.0
|
||||
version: 13.1.0(vue@3.5.22(typescript@5.8.3))
|
||||
version: 13.1.0(vue@3.5.24(typescript@5.8.3))
|
||||
axios:
|
||||
specifier: ^1.10.0
|
||||
version: 1.10.0
|
||||
@ -52,34 +52,34 @@ importers:
|
||||
version: 1.1.0
|
||||
naive-ui:
|
||||
specifier: ^2.42.0
|
||||
version: 2.42.0(vue@3.5.22(typescript@5.8.3))
|
||||
version: 2.42.0(vue@3.5.24(typescript@5.8.3))
|
||||
pinia:
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))
|
||||
version: 3.0.3(typescript@5.8.3)(vue@3.5.24(typescript@5.8.3))
|
||||
pinia-plugin-persistedstate:
|
||||
specifier: ^4.4.1
|
||||
version: 4.4.1(@nuxt/kit@3.15.0(rollup@4.40.0))(pinia@3.0.3(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3)))
|
||||
version: 4.4.1(@nuxt/kit@3.15.0(rollup@4.40.0))(pinia@3.0.3(typescript@5.8.3)(vue@3.5.24(typescript@5.8.3)))
|
||||
print-js:
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0
|
||||
vue:
|
||||
specifier: ^3.5.22
|
||||
version: 3.5.22(typescript@5.8.3)
|
||||
specifier: ^3.5.24
|
||||
version: 3.5.24(typescript@5.8.3)
|
||||
vue-demi:
|
||||
specifier: 0.14.10
|
||||
version: 0.14.10(vue@3.5.22(typescript@5.8.3))
|
||||
version: 0.14.10(vue@3.5.24(typescript@5.8.3))
|
||||
vue-hooks-plus:
|
||||
specifier: 2.4.1
|
||||
version: 2.4.1(vue@3.5.22(typescript@5.8.3))
|
||||
version: 2.4.1(vue@3.5.24(typescript@5.8.3))
|
||||
vue-i18n:
|
||||
specifier: ^9.13.1
|
||||
version: 9.13.1(vue@3.5.22(typescript@5.8.3))
|
||||
version: 9.13.1(vue@3.5.24(typescript@5.8.3))
|
||||
vue-router:
|
||||
specifier: ^4.6.3
|
||||
version: 4.6.3(vue@3.5.22(typescript@5.8.3))
|
||||
version: 4.6.3(vue@3.5.24(typescript@5.8.3))
|
||||
vue3-next-qrcode:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2(vue@3.5.22(typescript@5.8.3))
|
||||
version: 3.0.2(vue@3.5.24(typescript@5.8.3))
|
||||
devDependencies:
|
||||
'@commitlint/cli':
|
||||
specifier: 19.7.1
|
||||
@ -98,7 +98,7 @@ importers:
|
||||
version: 1.10.27
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: 4.0.0
|
||||
version: 4.0.0(rollup@4.40.0)(vue-i18n@9.13.1(vue@3.5.22(typescript@5.8.3)))(webpack-sources@3.2.3)
|
||||
version: 4.0.0(rollup@4.40.0)(vue-i18n@9.13.1(vue@3.5.24(typescript@5.8.3)))(webpack-sources@3.2.3)
|
||||
'@types/crypto-js':
|
||||
specifier: 4.2.2
|
||||
version: 4.2.2
|
||||
@ -119,10 +119,10 @@ importers:
|
||||
version: 8.36.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: 6.0.1
|
||||
version: 6.0.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
version: 6.0.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
'@vitejs/plugin-vue-jsx':
|
||||
specifier: 5.1.1
|
||||
version: 5.1.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
version: 5.1.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
'@vitest/ui':
|
||||
specifier: 3.0.5
|
||||
version: 3.0.5(vitest@2.1.8)
|
||||
@ -145,11 +145,11 @@ importers:
|
||||
specifier: 9.31.0
|
||||
version: 9.31.0(jiti@2.4.2)
|
||||
eslint-config-prettier:
|
||||
specifier: 10.1.5
|
||||
version: 10.1.5(eslint@9.31.0(jiti@2.4.2))
|
||||
specifier: 10.1.8
|
||||
version: 10.1.8(eslint@9.31.0(jiti@2.4.2))
|
||||
eslint-plugin-prettier:
|
||||
specifier: 5.5.1
|
||||
version: 5.5.1(@types/eslint@8.56.6)(eslint-config-prettier@10.1.5(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2)
|
||||
specifier: 5.5.4
|
||||
version: 5.5.4(@types/eslint@8.56.6)(eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2)
|
||||
eslint-plugin-vue:
|
||||
specifier: 9.32.0
|
||||
version: 9.32.0(eslint@9.31.0(jiti@2.4.2))
|
||||
@ -188,13 +188,13 @@ importers:
|
||||
version: 5.8.3
|
||||
unocss:
|
||||
specifier: 66.3.3
|
||||
version: 66.3.3(postcss@8.5.6)(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
version: 66.3.3(postcss@8.5.6)(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
unplugin-auto-import:
|
||||
specifier: 19.1.2
|
||||
version: 19.1.2(@nuxt/kit@3.15.0(rollup@4.40.0))(@vueuse/core@13.1.0(vue@3.5.22(typescript@5.8.3)))
|
||||
version: 19.1.2(@nuxt/kit@3.15.0(rollup@4.40.0))(@vueuse/core@13.1.0(vue@3.5.24(typescript@5.8.3)))
|
||||
unplugin-vue-components:
|
||||
specifier: 0.28.0
|
||||
version: 0.28.0(@babel/parser@7.28.5)(@nuxt/kit@3.15.0(rollup@4.40.0))(rollup@4.40.0)(vue@3.5.22(typescript@5.8.3))
|
||||
version: 0.28.0(@babel/parser@7.28.5)(@nuxt/kit@3.15.0(rollup@4.40.0))(rollup@4.40.0)(vue@3.5.24(typescript@5.8.3))
|
||||
vite:
|
||||
specifier: 6.3.5
|
||||
version: 6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
@ -221,7 +221,7 @@ importers:
|
||||
version: 2.0.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))
|
||||
vite-svg-loader:
|
||||
specifier: 5.1.0
|
||||
version: 5.1.0(vue@3.5.22(typescript@5.8.3))
|
||||
version: 5.1.0(vue@3.5.24(typescript@5.8.3))
|
||||
vitest:
|
||||
specifier: 2.1.8
|
||||
version: 2.1.8(@types/node@22.15.3)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(sass@1.86.3)
|
||||
@ -1664,6 +1664,9 @@ packages:
|
||||
'@vue/compiler-core@3.5.22':
|
||||
resolution: {integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==}
|
||||
|
||||
'@vue/compiler-core@3.5.24':
|
||||
resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==}
|
||||
|
||||
'@vue/compiler-dom@3.5.13':
|
||||
resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
|
||||
|
||||
@ -1673,18 +1676,27 @@ packages:
|
||||
'@vue/compiler-dom@3.5.22':
|
||||
resolution: {integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==}
|
||||
|
||||
'@vue/compiler-dom@3.5.24':
|
||||
resolution: {integrity: sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==}
|
||||
|
||||
'@vue/compiler-sfc@3.5.13':
|
||||
resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
|
||||
|
||||
'@vue/compiler-sfc@3.5.22':
|
||||
resolution: {integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==}
|
||||
|
||||
'@vue/compiler-sfc@3.5.24':
|
||||
resolution: {integrity: sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==}
|
||||
|
||||
'@vue/compiler-ssr@3.5.13':
|
||||
resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
|
||||
|
||||
'@vue/compiler-ssr@3.5.22':
|
||||
resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==}
|
||||
|
||||
'@vue/compiler-ssr@3.5.24':
|
||||
resolution: {integrity: sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==}
|
||||
|
||||
'@vue/compiler-vue2@2.7.16':
|
||||
resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
|
||||
|
||||
@ -1731,19 +1743,19 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@vue/reactivity@3.5.22':
|
||||
resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==}
|
||||
'@vue/reactivity@3.5.24':
|
||||
resolution: {integrity: sha512-BM8kBhtlkkbnyl4q+HiF5R5BL0ycDPfihowulm02q3WYp2vxgPcJuZO866qa/0u3idbMntKEtVNuAUp5bw4teg==}
|
||||
|
||||
'@vue/runtime-core@3.5.22':
|
||||
resolution: {integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==}
|
||||
'@vue/runtime-core@3.5.24':
|
||||
resolution: {integrity: sha512-RYP/byyKDgNIqfX/gNb2PB55dJmM97jc9wyF3jK7QUInYKypK2exmZMNwnjueWwGceEkP6NChd3D2ZVEp9undQ==}
|
||||
|
||||
'@vue/runtime-dom@3.5.22':
|
||||
resolution: {integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==}
|
||||
'@vue/runtime-dom@3.5.24':
|
||||
resolution: {integrity: sha512-Z8ANhr/i0XIluonHVjbUkjvn+CyrxbXRIxR7wn7+X7xlcb7dJsfITZbkVOeJZdP8VZwfrWRsWdShH6pngMxRjw==}
|
||||
|
||||
'@vue/server-renderer@3.5.22':
|
||||
resolution: {integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==}
|
||||
'@vue/server-renderer@3.5.24':
|
||||
resolution: {integrity: sha512-Yh2j2Y4G/0/4z/xJ1Bad4mxaAk++C2v4kaa8oSYTMJBJ00/ndPuxCnWeot0/7/qafQFLh5pr6xeV6SdMcE/G1w==}
|
||||
peerDependencies:
|
||||
vue: 3.5.22
|
||||
vue: 3.5.24
|
||||
|
||||
'@vue/shared@3.5.13':
|
||||
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
|
||||
@ -1754,6 +1766,9 @@ packages:
|
||||
'@vue/shared@3.5.22':
|
||||
resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==}
|
||||
|
||||
'@vue/shared@3.5.24':
|
||||
resolution: {integrity: sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==}
|
||||
|
||||
'@vue/test-utils@2.4.6':
|
||||
resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==}
|
||||
|
||||
@ -2635,20 +2650,20 @@ packages:
|
||||
engines: {node: '>=6.0'}
|
||||
hasBin: true
|
||||
|
||||
eslint-config-prettier@10.1.5:
|
||||
resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==}
|
||||
eslint-config-prettier@10.1.8:
|
||||
resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
|
||||
eslint-config-prettier@9.1.0:
|
||||
resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
|
||||
eslint-config-prettier@9.1.2:
|
||||
resolution: {integrity: sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
|
||||
eslint-plugin-prettier@5.5.1:
|
||||
resolution: {integrity: sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==}
|
||||
eslint-plugin-prettier@5.5.4:
|
||||
resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
'@types/eslint': '>=8.0.0'
|
||||
@ -4893,8 +4908,8 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.0.1
|
||||
|
||||
vue@3.5.22:
|
||||
resolution: {integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==}
|
||||
vue@3.5.24:
|
||||
resolution: {integrity: sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
@ -5541,9 +5556,9 @@ snapshots:
|
||||
dependencies:
|
||||
css-render: 0.15.14
|
||||
|
||||
'@css-render/vue3-ssr@0.15.14(vue@3.5.22(typescript@5.8.3))':
|
||||
'@css-render/vue3-ssr@0.15.14(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
'@emotion/hash@0.8.0': {}
|
||||
|
||||
@ -5774,7 +5789,7 @@ snapshots:
|
||||
|
||||
'@interactjs/types@1.10.27': {}
|
||||
|
||||
'@intlify/bundle-utils@8.0.0(vue-i18n@9.13.1(vue@3.5.22(typescript@5.8.3)))':
|
||||
'@intlify/bundle-utils@8.0.0(vue-i18n@9.13.1(vue@3.5.24(typescript@5.8.3)))':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 9.13.1
|
||||
'@intlify/shared': 9.13.1
|
||||
@ -5786,7 +5801,7 @@ snapshots:
|
||||
source-map-js: 1.2.1
|
||||
yaml-eslint-parser: 1.2.2
|
||||
optionalDependencies:
|
||||
vue-i18n: 9.13.1(vue@3.5.22(typescript@5.8.3))
|
||||
vue-i18n: 9.13.1(vue@3.5.24(typescript@5.8.3))
|
||||
|
||||
'@intlify/core-base@9.13.1':
|
||||
dependencies:
|
||||
@ -5800,9 +5815,9 @@ snapshots:
|
||||
|
||||
'@intlify/shared@9.13.1': {}
|
||||
|
||||
'@intlify/unplugin-vue-i18n@4.0.0(rollup@4.40.0)(vue-i18n@9.13.1(vue@3.5.22(typescript@5.8.3)))(webpack-sources@3.2.3)':
|
||||
'@intlify/unplugin-vue-i18n@4.0.0(rollup@4.40.0)(vue-i18n@9.13.1(vue@3.5.24(typescript@5.8.3)))(webpack-sources@3.2.3)':
|
||||
dependencies:
|
||||
'@intlify/bundle-utils': 8.0.0(vue-i18n@9.13.1(vue@3.5.22(typescript@5.8.3)))
|
||||
'@intlify/bundle-utils': 8.0.0(vue-i18n@9.13.1(vue@3.5.24(typescript@5.8.3)))
|
||||
'@intlify/shared': 9.13.1
|
||||
'@rollup/pluginutils': 5.1.2(rollup@4.40.0)
|
||||
'@vue/compiler-sfc': 3.5.13
|
||||
@ -5815,7 +5830,7 @@ snapshots:
|
||||
source-map-js: 1.2.1
|
||||
unplugin: 1.14.1(webpack-sources@3.2.3)
|
||||
optionalDependencies:
|
||||
vue-i18n: 9.13.1(vue@3.5.22(typescript@5.8.3))
|
||||
vue-i18n: 9.13.1(vue@3.5.24(typescript@5.8.3))
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
@ -6354,11 +6369,11 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.36.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
'@unocss/astro@66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))':
|
||||
'@unocss/astro@66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@unocss/core': 66.3.3
|
||||
'@unocss/reset': 66.3.3
|
||||
'@unocss/vite': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
'@unocss/vite': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
optionalDependencies:
|
||||
vite: 6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
transitivePeerDependencies:
|
||||
@ -6391,14 +6406,14 @@ snapshots:
|
||||
dependencies:
|
||||
'@unocss/core': 66.3.3
|
||||
|
||||
'@unocss/inspector@66.3.3(vue@3.5.22(typescript@5.8.3))':
|
||||
'@unocss/inspector@66.3.3(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@unocss/core': 66.3.3
|
||||
'@unocss/rule-utils': 66.3.3
|
||||
colorette: 2.0.20
|
||||
gzip-size: 6.0.0
|
||||
sirv: 3.0.1
|
||||
vue-flow-layout: 0.1.1(vue@3.5.22(typescript@5.8.3))
|
||||
vue-flow-layout: 0.1.1(vue@3.5.24(typescript@5.8.3))
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
@ -6491,12 +6506,12 @@ snapshots:
|
||||
dependencies:
|
||||
'@unocss/core': 66.3.3
|
||||
|
||||
'@unocss/vite@66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))':
|
||||
'@unocss/vite@66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
'@unocss/config': 66.3.3
|
||||
'@unocss/core': 66.3.3
|
||||
'@unocss/inspector': 66.3.3(vue@3.5.22(typescript@5.8.3))
|
||||
'@unocss/inspector': 66.3.3(vue@3.5.24(typescript@5.8.3))
|
||||
chokidar: 3.6.0
|
||||
magic-string: 0.30.17
|
||||
pathe: 2.0.3
|
||||
@ -6506,7 +6521,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
'@vitejs/plugin-vue-jsx@5.1.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))':
|
||||
'@vitejs/plugin-vue-jsx@5.1.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5)
|
||||
@ -6514,15 +6529,15 @@ snapshots:
|
||||
'@rolldown/pluginutils': 1.0.0-beta.44
|
||||
'@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.5)
|
||||
vite: 6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@vitejs/plugin-vue@6.0.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))':
|
||||
'@vitejs/plugin-vue@6.0.1(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-beta.29
|
||||
vite: 6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
'@vitest/expect@2.1.8':
|
||||
dependencies:
|
||||
@ -6650,6 +6665,14 @@ snapshots:
|
||||
estree-walker: 2.0.2
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-core@3.5.24':
|
||||
dependencies:
|
||||
'@babel/parser': 7.28.5
|
||||
'@vue/shared': 3.5.24
|
||||
entities: 4.5.0
|
||||
estree-walker: 2.0.2
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-dom@3.5.13':
|
||||
dependencies:
|
||||
'@vue/compiler-core': 3.5.13
|
||||
@ -6665,6 +6688,11 @@ snapshots:
|
||||
'@vue/compiler-core': 3.5.22
|
||||
'@vue/shared': 3.5.22
|
||||
|
||||
'@vue/compiler-dom@3.5.24':
|
||||
dependencies:
|
||||
'@vue/compiler-core': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
|
||||
'@vue/compiler-sfc@3.5.13':
|
||||
dependencies:
|
||||
'@babel/parser': 7.26.2
|
||||
@ -6689,6 +6717,18 @@ snapshots:
|
||||
postcss: 8.5.6
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-sfc@3.5.24':
|
||||
dependencies:
|
||||
'@babel/parser': 7.28.5
|
||||
'@vue/compiler-core': 3.5.24
|
||||
'@vue/compiler-dom': 3.5.24
|
||||
'@vue/compiler-ssr': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
estree-walker: 2.0.2
|
||||
magic-string: 0.30.21
|
||||
postcss: 8.5.6
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-ssr@3.5.13':
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.5.13
|
||||
@ -6699,6 +6739,11 @@ snapshots:
|
||||
'@vue/compiler-dom': 3.5.22
|
||||
'@vue/shared': 3.5.22
|
||||
|
||||
'@vue/compiler-ssr@3.5.24':
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
|
||||
'@vue/compiler-vue2@2.7.16':
|
||||
dependencies:
|
||||
de-indent: 1.0.2
|
||||
@ -6733,8 +6778,8 @@ snapshots:
|
||||
'@vue/eslint-config-prettier@10.1.0(@types/eslint@8.56.6)(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2)':
|
||||
dependencies:
|
||||
eslint: 9.31.0(jiti@2.4.2)
|
||||
eslint-config-prettier: 9.1.0(eslint@9.31.0(jiti@2.4.2))
|
||||
eslint-plugin-prettier: 5.5.1(@types/eslint@8.56.6)(eslint-config-prettier@9.1.0(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2)
|
||||
eslint-config-prettier: 9.1.2(eslint@9.31.0(jiti@2.4.2))
|
||||
eslint-plugin-prettier: 5.5.4(@types/eslint@8.56.6)(eslint-config-prettier@9.1.2(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2)
|
||||
prettier: 3.6.2
|
||||
transitivePeerDependencies:
|
||||
- '@types/eslint'
|
||||
@ -6764,27 +6809,27 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
'@vue/reactivity@3.5.22':
|
||||
'@vue/reactivity@3.5.24':
|
||||
dependencies:
|
||||
'@vue/shared': 3.5.22
|
||||
'@vue/shared': 3.5.24
|
||||
|
||||
'@vue/runtime-core@3.5.22':
|
||||
'@vue/runtime-core@3.5.24':
|
||||
dependencies:
|
||||
'@vue/reactivity': 3.5.22
|
||||
'@vue/shared': 3.5.22
|
||||
'@vue/reactivity': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
|
||||
'@vue/runtime-dom@3.5.22':
|
||||
'@vue/runtime-dom@3.5.24':
|
||||
dependencies:
|
||||
'@vue/reactivity': 3.5.22
|
||||
'@vue/runtime-core': 3.5.22
|
||||
'@vue/shared': 3.5.22
|
||||
'@vue/reactivity': 3.5.24
|
||||
'@vue/runtime-core': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
csstype: 3.1.3
|
||||
|
||||
'@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.8.3))':
|
||||
'@vue/server-renderer@3.5.24(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@vue/compiler-ssr': 3.5.22
|
||||
'@vue/shared': 3.5.22
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
'@vue/compiler-ssr': 3.5.24
|
||||
'@vue/shared': 3.5.24
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
'@vue/shared@3.5.13': {}
|
||||
|
||||
@ -6792,23 +6837,25 @@ snapshots:
|
||||
|
||||
'@vue/shared@3.5.22': {}
|
||||
|
||||
'@vue/shared@3.5.24': {}
|
||||
|
||||
'@vue/test-utils@2.4.6':
|
||||
dependencies:
|
||||
js-beautify: 1.15.1
|
||||
vue-component-type-helpers: 2.0.13
|
||||
|
||||
'@vueuse/core@13.1.0(vue@3.5.22(typescript@5.8.3))':
|
||||
'@vueuse/core@13.1.0(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@types/web-bluetooth': 0.0.21
|
||||
'@vueuse/metadata': 13.1.0
|
||||
'@vueuse/shared': 13.1.0(vue@3.5.22(typescript@5.8.3))
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
'@vueuse/shared': 13.1.0(vue@3.5.24(typescript@5.8.3))
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
'@vueuse/metadata@13.1.0': {}
|
||||
|
||||
'@vueuse/shared@13.1.0(vue@3.5.22(typescript@5.8.3))':
|
||||
'@vueuse/shared@13.1.0(vue@3.5.24(typescript@5.8.3))':
|
||||
dependencies:
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
'@xn-sakina/rml-darwin-arm64@2.3.0':
|
||||
optional: true
|
||||
@ -7688,15 +7735,15 @@ snapshots:
|
||||
optionalDependencies:
|
||||
source-map: 0.6.1
|
||||
|
||||
eslint-config-prettier@10.1.5(eslint@9.31.0(jiti@2.4.2)):
|
||||
eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
eslint: 9.31.0(jiti@2.4.2)
|
||||
|
||||
eslint-config-prettier@9.1.0(eslint@9.31.0(jiti@2.4.2)):
|
||||
eslint-config-prettier@9.1.2(eslint@9.31.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
eslint: 9.31.0(jiti@2.4.2)
|
||||
|
||||
eslint-plugin-prettier@5.5.1(@types/eslint@8.56.6)(eslint-config-prettier@10.1.5(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2):
|
||||
eslint-plugin-prettier@5.5.4(@types/eslint@8.56.6)(eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2):
|
||||
dependencies:
|
||||
eslint: 9.31.0(jiti@2.4.2)
|
||||
prettier: 3.6.2
|
||||
@ -7704,9 +7751,9 @@ snapshots:
|
||||
synckit: 0.11.8
|
||||
optionalDependencies:
|
||||
'@types/eslint': 8.56.6
|
||||
eslint-config-prettier: 10.1.5(eslint@9.31.0(jiti@2.4.2))
|
||||
eslint-config-prettier: 10.1.8(eslint@9.31.0(jiti@2.4.2))
|
||||
|
||||
eslint-plugin-prettier@5.5.1(@types/eslint@8.56.6)(eslint-config-prettier@9.1.0(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2):
|
||||
eslint-plugin-prettier@5.5.4(@types/eslint@8.56.6)(eslint-config-prettier@9.1.2(eslint@9.31.0(jiti@2.4.2)))(eslint@9.31.0(jiti@2.4.2))(prettier@3.6.2):
|
||||
dependencies:
|
||||
eslint: 9.31.0(jiti@2.4.2)
|
||||
prettier: 3.6.2
|
||||
@ -7714,7 +7761,7 @@ snapshots:
|
||||
synckit: 0.11.8
|
||||
optionalDependencies:
|
||||
'@types/eslint': 8.56.6
|
||||
eslint-config-prettier: 9.1.0(eslint@9.31.0(jiti@2.4.2))
|
||||
eslint-config-prettier: 9.1.2(eslint@9.31.0(jiti@2.4.2))
|
||||
|
||||
eslint-plugin-vue@9.32.0(eslint@9.31.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
@ -8755,10 +8802,10 @@ snapshots:
|
||||
arrify: 2.0.1
|
||||
minimatch: 3.1.2
|
||||
|
||||
naive-ui@2.42.0(vue@3.5.22(typescript@5.8.3)):
|
||||
naive-ui@2.42.0(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@css-render/plugin-bem': 0.15.14(css-render@0.15.14)
|
||||
'@css-render/vue3-ssr': 0.15.14(vue@3.5.22(typescript@5.8.3))
|
||||
'@css-render/vue3-ssr': 0.15.14(vue@3.5.24(typescript@5.8.3))
|
||||
'@types/katex': 0.16.7
|
||||
'@types/lodash': 4.17.15
|
||||
'@types/lodash-es': 4.17.12
|
||||
@ -8773,10 +8820,10 @@ snapshots:
|
||||
lodash-es: 4.17.21
|
||||
seemly: 0.3.9
|
||||
treemate: 0.3.11
|
||||
vdirs: 0.1.8(vue@3.5.22(typescript@5.8.3))
|
||||
vooks: 0.2.12(vue@3.5.22(typescript@5.8.3))
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vueuc: 0.4.65(vue@3.5.22(typescript@5.8.3))
|
||||
vdirs: 0.1.8(vue@3.5.24(typescript@5.8.3))
|
||||
vooks: 0.2.12(vue@3.5.24(typescript@5.8.3))
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
vueuc: 0.4.65(vue@3.5.24(typescript@5.8.3))
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
@ -8970,19 +9017,19 @@ snapshots:
|
||||
|
||||
pidtree@0.6.0: {}
|
||||
|
||||
pinia-plugin-persistedstate@4.4.1(@nuxt/kit@3.15.0(rollup@4.40.0))(pinia@3.0.3(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))):
|
||||
pinia-plugin-persistedstate@4.4.1(@nuxt/kit@3.15.0(rollup@4.40.0))(pinia@3.0.3(typescript@5.8.3)(vue@3.5.24(typescript@5.8.3))):
|
||||
dependencies:
|
||||
deep-pick-omit: 1.2.1
|
||||
defu: 6.1.4
|
||||
destr: 2.0.5
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.15.0(rollup@4.40.0)
|
||||
pinia: 3.0.3(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3))
|
||||
pinia: 3.0.3(typescript@5.8.3)(vue@3.5.24(typescript@5.8.3))
|
||||
|
||||
pinia@3.0.3(typescript@5.8.3)(vue@3.5.22(typescript@5.8.3)):
|
||||
pinia@3.0.3(typescript@5.8.3)(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-api': 7.7.5
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
@ -9707,9 +9754,9 @@ snapshots:
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
unocss@66.3.3(postcss@8.5.6)(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3)):
|
||||
unocss@66.3.3(postcss@8.5.6)(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@unocss/astro': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
'@unocss/astro': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
'@unocss/cli': 66.3.3
|
||||
'@unocss/core': 66.3.3
|
||||
'@unocss/postcss': 66.3.3(postcss@8.5.6)
|
||||
@ -9727,7 +9774,7 @@ snapshots:
|
||||
'@unocss/transformer-compile-class': 66.3.3
|
||||
'@unocss/transformer-directives': 66.3.3
|
||||
'@unocss/transformer-variant-group': 66.3.3
|
||||
'@unocss/vite': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.22(typescript@5.8.3))
|
||||
'@unocss/vite': 66.3.3(vite@6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))(vue@3.5.24(typescript@5.8.3))
|
||||
optionalDependencies:
|
||||
vite: 6.3.5(@types/node@22.15.3)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)
|
||||
transitivePeerDependencies:
|
||||
@ -9737,7 +9784,7 @@ snapshots:
|
||||
|
||||
unpipe@1.0.0: {}
|
||||
|
||||
unplugin-auto-import@19.1.2(@nuxt/kit@3.15.0(rollup@4.40.0))(@vueuse/core@13.1.0(vue@3.5.22(typescript@5.8.3))):
|
||||
unplugin-auto-import@19.1.2(@nuxt/kit@3.15.0(rollup@4.40.0))(@vueuse/core@13.1.0(vue@3.5.24(typescript@5.8.3))):
|
||||
dependencies:
|
||||
local-pkg: 1.1.1
|
||||
magic-string: 0.30.17
|
||||
@ -9747,14 +9794,14 @@ snapshots:
|
||||
unplugin-utils: 0.2.4
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.15.0(rollup@4.40.0)
|
||||
'@vueuse/core': 13.1.0(vue@3.5.22(typescript@5.8.3))
|
||||
'@vueuse/core': 13.1.0(vue@3.5.24(typescript@5.8.3))
|
||||
|
||||
unplugin-utils@0.2.4:
|
||||
dependencies:
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.2
|
||||
|
||||
unplugin-vue-components@0.28.0(@babel/parser@7.28.5)(@nuxt/kit@3.15.0(rollup@4.40.0))(rollup@4.40.0)(vue@3.5.22(typescript@5.8.3)):
|
||||
unplugin-vue-components@0.28.0(@babel/parser@7.28.5)(@nuxt/kit@3.15.0(rollup@4.40.0))(rollup@4.40.0)(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@antfu/utils': 0.7.10
|
||||
'@rollup/pluginutils': 5.1.4(rollup@4.40.0)
|
||||
@ -9766,7 +9813,7 @@ snapshots:
|
||||
minimatch: 9.0.5
|
||||
mlly: 1.7.3
|
||||
unplugin: 2.1.0
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
optionalDependencies:
|
||||
'@babel/parser': 7.28.5
|
||||
'@nuxt/kit': 3.15.0(rollup@4.40.0)
|
||||
@ -9857,10 +9904,10 @@ snapshots:
|
||||
|
||||
vary@1.1.2: {}
|
||||
|
||||
vdirs@0.1.8(vue@3.5.22(typescript@5.8.3)):
|
||||
vdirs@0.1.8(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
evtd: 0.2.4
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vite-bundle-analyzer@0.16.0: {}
|
||||
|
||||
@ -9966,10 +10013,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-svg-loader@5.1.0(vue@3.5.22(typescript@5.8.3)):
|
||||
vite-svg-loader@5.1.0(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
svgo: 3.3.2
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vite@5.4.19(@types/node@22.15.3)(sass@1.86.3):
|
||||
dependencies:
|
||||
@ -10033,18 +10080,18 @@ snapshots:
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vooks@0.2.12(vue@3.5.22(typescript@5.8.3)):
|
||||
vooks@0.2.12(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
evtd: 0.2.4
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vscode-uri@3.1.0: {}
|
||||
|
||||
vue-component-type-helpers@2.0.13: {}
|
||||
|
||||
vue-demi@0.14.10(vue@3.5.22(typescript@5.8.3)):
|
||||
vue-demi@0.14.10(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue-eslint-parser@9.4.3(eslint@9.31.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
@ -10059,30 +10106,30 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vue-flow-layout@0.1.1(vue@3.5.22(typescript@5.8.3)):
|
||||
vue-flow-layout@0.1.1(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue-hooks-plus@2.4.1(vue@3.5.22(typescript@5.8.3)):
|
||||
vue-hooks-plus@2.4.1(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@types/js-cookie': 3.0.6
|
||||
'@vue/devtools-api': 7.7.2
|
||||
js-cookie: 3.0.5
|
||||
lodash-es: 4.17.21
|
||||
screenfull: 5.2.0
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue-i18n@9.13.1(vue@3.5.22(typescript@5.8.3)):
|
||||
vue-i18n@9.13.1(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.13.1
|
||||
'@intlify/shared': 9.13.1
|
||||
'@vue/devtools-api': 6.6.1
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue-router@4.6.3(vue@3.5.22(typescript@5.8.3)):
|
||||
vue-router@4.6.3(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-api': 6.6.4
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue-tsc@2.2.8(typescript@5.8.3):
|
||||
dependencies:
|
||||
@ -10090,31 +10137,31 @@ snapshots:
|
||||
'@vue/language-core': 2.2.8(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
|
||||
vue3-next-qrcode@3.0.2(vue@3.5.22(typescript@5.8.3)):
|
||||
vue3-next-qrcode@3.0.2(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
js-binary-schema-parser: 2.0.3
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
vue@3.5.22(typescript@5.8.3):
|
||||
vue@3.5.24(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.5.22
|
||||
'@vue/compiler-sfc': 3.5.22
|
||||
'@vue/runtime-dom': 3.5.22
|
||||
'@vue/server-renderer': 3.5.22(vue@3.5.22(typescript@5.8.3))
|
||||
'@vue/shared': 3.5.22
|
||||
'@vue/compiler-dom': 3.5.24
|
||||
'@vue/compiler-sfc': 3.5.24
|
||||
'@vue/runtime-dom': 3.5.24
|
||||
'@vue/server-renderer': 3.5.24(vue@3.5.24(typescript@5.8.3))
|
||||
'@vue/shared': 3.5.24
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
vueuc@0.4.65(vue@3.5.22(typescript@5.8.3)):
|
||||
vueuc@0.4.65(vue@3.5.24(typescript@5.8.3)):
|
||||
dependencies:
|
||||
'@css-render/vue3-ssr': 0.15.14(vue@3.5.22(typescript@5.8.3))
|
||||
'@css-render/vue3-ssr': 0.15.14(vue@3.5.24(typescript@5.8.3))
|
||||
'@juggle/resize-observer': 3.4.0
|
||||
css-render: 0.15.14
|
||||
evtd: 0.2.4
|
||||
seemly: 0.3.9
|
||||
vdirs: 0.1.8(vue@3.5.22(typescript@5.8.3))
|
||||
vooks: 0.2.12(vue@3.5.22(typescript@5.8.3))
|
||||
vue: 3.5.22(typescript@5.8.3)
|
||||
vdirs: 0.1.8(vue@3.5.24(typescript@5.8.3))
|
||||
vooks: 0.2.12(vue@3.5.24(typescript@5.8.3))
|
||||
vue: 3.5.24(typescript@5.8.3)
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
|
||||
@ -12,8 +12,8 @@ import type { MessageProviderProps } from 'naive-ui'
|
||||
export const GLOBAL_CLASS_NAMES = {
|
||||
darkClassName: 'ray-template--dark',
|
||||
lightClassName: 'ray-template--light',
|
||||
rayTemplateThemePrimaryColor: '--ray-theme-primary-color',
|
||||
rayTemplateThemePrimaryFadeColor: '--ray-theme-primary-fade-color',
|
||||
rayTemplateThemePrimaryColor: '--r-theme-primary-color',
|
||||
rayTemplateThemePrimaryFadeColor: '--r-theme-primary-fade-color',
|
||||
preLoadingAnimation: 'pre-loading-animation',
|
||||
htmlHeight: '--html-height',
|
||||
htmlWidth: '--html-width',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useAxiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import { axiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import implement from './provider'
|
||||
|
||||
const { setImplement } = useAxiosInterceptor()
|
||||
const { setImplement } = axiosInterceptor()
|
||||
|
||||
export const setupRequestInterceptor = () => {
|
||||
const { implementRequestInterceptorArray } = implement
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useAxiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import { axiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import implement from './provider'
|
||||
|
||||
const { setImplement } = useAxiosInterceptor()
|
||||
const { setImplement } = axiosInterceptor()
|
||||
|
||||
export const setupResponseInterceptor = () => {
|
||||
const { implementResponseInterceptorArray } = implement
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import { AXIOS_CONFIG } from '@/app-config'
|
||||
import { useAxiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import { axiosInterceptor } from '@/axios/utils/interceptor'
|
||||
import {
|
||||
setupResponseInterceptor,
|
||||
setupResponseErrorInterceptor,
|
||||
@ -15,7 +15,7 @@ import type { AxiosInstanceExpand, RequestInterceptorConfig } from './types'
|
||||
// 创建 axios 实例
|
||||
const server: AxiosInstanceExpand = axios.create(AXIOS_CONFIG)
|
||||
// 获取拦截器实例
|
||||
const { createAxiosInstance, beforeFetch, fetchError } = useAxiosInterceptor()
|
||||
const { createAxiosInstance, beforeFetch, fetchError } = axiosInterceptor()
|
||||
|
||||
// 请求拦截器
|
||||
server.interceptors.request.use(
|
||||
|
||||
@ -1,116 +1,129 @@
|
||||
/**
|
||||
*
|
||||
* 自动取消重复请求
|
||||
*
|
||||
* 可以根据自己项目进行定制化配置
|
||||
*/
|
||||
|
||||
import type { AppRawRequestConfig, CancelerParams } from '@/axios/types'
|
||||
|
||||
/**
|
||||
*
|
||||
* @class RequestCanceler
|
||||
*
|
||||
* @description
|
||||
* 用于取消重复请求,会在请求前添加 signal 属性,用于取消请求。
|
||||
* 通过 generateRequestKey 方法生成请求 key,用于标识请求。
|
||||
* 请求取消器。
|
||||
*
|
||||
* 如果需要取消请求,则需要在请求前添加 cancelConfig.cancel 为 true;
|
||||
* 并且会在请求前添加 __CANCELER_TAG_RAY_TEMPLATE__ 属性,用于标识是否需要取消。
|
||||
* 用于管理和取消重复的 HTTP 请求:
|
||||
* - 自动为请求添加 AbortController signal
|
||||
* - 通过请求特征生成唯一 key 来识别重复请求
|
||||
* - 支持取消单个或所有待处理的请求
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const canceler = new RequestCanceler()
|
||||
*
|
||||
* // 添加请求到待处理队列
|
||||
* canceler.addPendingRequest(config)
|
||||
*
|
||||
* // 移除并取消特定请求
|
||||
* canceler.removePendingRequest(config)
|
||||
*
|
||||
* // 取消所有待处理请求
|
||||
* canceler.cancelAllRequest()
|
||||
* ```
|
||||
*/
|
||||
export default class RequestCanceler {
|
||||
private pendingRequest: Map<string, AbortController>
|
||||
|
||||
constructor() {
|
||||
this.pendingRequest = new Map<string, AbortController>()
|
||||
}
|
||||
/** 待处理请求的 Map,key 为请求标识,value 为 AbortController */
|
||||
private readonly pendingRequest = new Map<string, AbortController>()
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config 请求体 config
|
||||
* @param config - 请求配置
|
||||
*
|
||||
* @returns 是否需要添加取消功能,默认为 true
|
||||
*
|
||||
* @description
|
||||
* 判断是否需要添加 signal 属性。
|
||||
*
|
||||
* 如果 cancelConfig 为 false,则不添加 signal 属性;
|
||||
* 如果 cancelConfig 为 true,则添加 signal 属性。
|
||||
*
|
||||
* @example
|
||||
* const bool = isAppending(config) // true or false
|
||||
* 判断请求是否需要添加取消功能。
|
||||
*/
|
||||
private isAppending(config: AppRawRequestConfig | CancelerParams) {
|
||||
private shouldAddCanceler(
|
||||
config: AppRawRequestConfig | CancelerParams,
|
||||
): boolean {
|
||||
return config.cancelConfig?.cancel ?? true
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config 请求体 config
|
||||
* @param config - 请求配置
|
||||
*
|
||||
* @returns 请求的唯一标识字符串
|
||||
*
|
||||
* @description
|
||||
* 根据当前请求生成 key。
|
||||
*
|
||||
* @example
|
||||
* const key = generateRequestKey(config) // string
|
||||
* 基于 URL、方法、参数和数据生成请求的唯一标识 key。
|
||||
*/
|
||||
private generateRequestKey(config: AppRawRequestConfig | CancelerParams) {
|
||||
const { method, url } = config
|
||||
private generateRequestKey(
|
||||
config: AppRawRequestConfig | CancelerParams,
|
||||
): string {
|
||||
const { method = '', url = '', params, data } = config
|
||||
|
||||
return [
|
||||
url || '',
|
||||
method || '',
|
||||
JSON.stringify(config.params),
|
||||
JSON.stringify(config.data),
|
||||
].join('&')
|
||||
return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config axios request config
|
||||
*
|
||||
|
||||
* @param config - Axios 请求配置
|
||||
|
||||
* @description
|
||||
* 添加请求到 pendingRequest map 中,用于取消请求。
|
||||
* 并且如果已经存在该请求,则会取消上次请求,并且重新挂载 signal。
|
||||
*
|
||||
* 如果不需要该请求被挂载,则需要在请求前添加 cancelConfig.cancel 为 false。
|
||||
* 如果该请求需要被取消,则会添加 __CANCELER_TAG_RAY_TEMPLATE__ 属性,标记是否需要取消。
|
||||
*
|
||||
|
||||
* @example
|
||||
* addPendingRequest(config)
|
||||
* ```ts
|
||||
* // 默认启用取消功能
|
||||
* canceler.addPendingRequest(config)
|
||||
*
|
||||
* // 禁用取消功能
|
||||
* canceler.addPendingRequest({
|
||||
* ...config,
|
||||
* cancelConfig: { cancel: false }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
addPendingRequest(config: AppRawRequestConfig | CancelerParams) {
|
||||
if (this.isAppending(config)) {
|
||||
config.__CANCELER_TAG_RAY_TEMPLATE__ = '__CANCELER_TAG_RAY_TEMPLATE__'
|
||||
addPendingRequest(config: AppRawRequestConfig | CancelerParams): void {
|
||||
if (!this.shouldAddCanceler(config)) {
|
||||
return
|
||||
}
|
||||
|
||||
const requestKey = this.generateRequestKey(config)
|
||||
config.__CANCELER_TAG_RAY_TEMPLATE__ = '__CANCELER_TAG_RAY_TEMPLATE__'
|
||||
|
||||
if (!this.pendingRequest.has(requestKey)) {
|
||||
const controller = new AbortController()
|
||||
const requestKey = this.generateRequestKey(config)
|
||||
const existingController = this.pendingRequest.get(requestKey)
|
||||
|
||||
config.signal = controller.signal
|
||||
if (existingController) {
|
||||
// 复用现有的 signal
|
||||
config.signal = existingController.signal
|
||||
} else {
|
||||
// 创建新的 AbortController
|
||||
const controller = new AbortController()
|
||||
|
||||
this.pendingRequest.set(requestKey, controller)
|
||||
} else {
|
||||
// 如果已经有该 key 则重新挂载 signal
|
||||
config.signal = this.pendingRequest.get(requestKey)?.signal
|
||||
}
|
||||
config.signal = controller.signal
|
||||
this.pendingRequest.set(requestKey, controller)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config axios request config
|
||||
* @param config - Axios 请求配置
|
||||
*
|
||||
* @description
|
||||
* 移除 pendingRequest map 中的请求,如果存在的话。
|
||||
* 移除并取消特定请求,
|
||||
* 从待处理队列中移除请求,并调用 abort() 取消该请求。
|
||||
*
|
||||
* @example
|
||||
* removePendingRequest(config)
|
||||
* ```ts
|
||||
* canceler.removePendingRequest(config)
|
||||
* ```
|
||||
*/
|
||||
removePendingRequest(config: AppRawRequestConfig | CancelerParams) {
|
||||
removePendingRequest(config: AppRawRequestConfig | CancelerParams): void {
|
||||
const requestKey = this.generateRequestKey(config)
|
||||
const controller = this.pendingRequest.get(requestKey)
|
||||
|
||||
if (this.pendingRequest.has(requestKey)) {
|
||||
this.pendingRequest.get(requestKey)!.abort()
|
||||
if (controller) {
|
||||
controller.abort()
|
||||
this.pendingRequest.delete(requestKey)
|
||||
}
|
||||
}
|
||||
@ -118,17 +131,50 @@ export default class RequestCanceler {
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 移除所有 pendingRequest map 中的请求。
|
||||
* 取消所有待处理的请求。
|
||||
*
|
||||
* 值得注意的是,该方法会一次性移除所有的请求,所以需要注意是否有需要在后台挂载的请求;
|
||||
* 如果有需要在后台挂载的请求,则需要在请求前添加 cancelConfig.cancel 为 false。
|
||||
* 遍历并取消队列中的所有请求,然后清空队列。
|
||||
*
|
||||
* ⚠️ 注意:此方法会取消所有请求,包括后台运行的请求。
|
||||
*
|
||||
* 如果某些请求不应被取消,请在请求配置中设置 `cancelConfig.cancel = false`
|
||||
*
|
||||
* @example
|
||||
* cancelAllRequest()
|
||||
* ```ts
|
||||
* // 在路由切换或组件卸载时取消所有请求
|
||||
* canceler.cancelAllRequest()
|
||||
* ```
|
||||
*/
|
||||
cancelAllRequest() {
|
||||
this.pendingRequest.forEach((curr) => {
|
||||
curr.abort()
|
||||
cancelAllRequest(): void {
|
||||
this.pendingRequest.forEach((controller) => {
|
||||
controller.abort()
|
||||
})
|
||||
this.pendingRequest.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns 待处理请求数量
|
||||
*
|
||||
* @description
|
||||
* 获取当前待处理请求的数量。
|
||||
*/
|
||||
getPendingCount(): number {
|
||||
return this.pendingRequest.size
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config - 请求配置
|
||||
*
|
||||
* @returns 是否存在于待处理队列
|
||||
*
|
||||
* @description
|
||||
* 检查特定请求是否在待处理队列中。
|
||||
*/
|
||||
hasPendingRequest(config: AppRawRequestConfig | CancelerParams): boolean {
|
||||
const requestKey = this.generateRequestKey(config)
|
||||
|
||||
return this.pendingRequest.has(requestKey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,64 +13,101 @@ import type {
|
||||
import type { AnyFC } from '@/types'
|
||||
import type { AxiosError } from 'axios'
|
||||
|
||||
type ImplementKeys = keyof ImplementQueue
|
||||
type ErrorImplementKeys = keyof ErrorImplementQueue
|
||||
|
||||
// 当前请求的实例
|
||||
const axiosFetchInstance: AxiosFetchInstance = {
|
||||
requestInstance: null,
|
||||
responseInstance: null,
|
||||
}
|
||||
|
||||
// 请求失败返回值
|
||||
const axiosFetchError: AxiosFetchError<AxiosError<unknown, unknown>> = {
|
||||
requestError: null,
|
||||
responseError: null,
|
||||
}
|
||||
|
||||
// 请求队列(区分 resolve 与 reject 状态)
|
||||
const implement: ImplementQueue = {
|
||||
implementRequestInterceptorArray: [],
|
||||
implementResponseInterceptorArray: [],
|
||||
}
|
||||
|
||||
// 请求失败队列
|
||||
const errorImplement: ErrorImplementQueue = {
|
||||
implementRequestInterceptorErrorArray: [],
|
||||
implementResponseInterceptorErrorArray: [],
|
||||
}
|
||||
|
||||
type ImplementKeys = keyof ImplementQueue
|
||||
|
||||
type ErrorImplementKeys = keyof ErrorImplementQueue
|
||||
|
||||
// 取消器实例
|
||||
export const axiosCanceler = new RequestCanceler()
|
||||
|
||||
export const useAxiosInterceptor = () => {
|
||||
// 创建拦截器实例
|
||||
export const axiosInterceptor = () => {
|
||||
/**
|
||||
*
|
||||
* @param instance - 请求或响应实例
|
||||
* @param instanceKey - 实例类型标识
|
||||
*
|
||||
* @description
|
||||
* 创建拦截器实例。
|
||||
*/
|
||||
const createAxiosInstance = (
|
||||
instance: RequestInterceptorConfig | ResponseInterceptorConfig,
|
||||
instanceKey: keyof AxiosFetchInstance,
|
||||
) => {
|
||||
instanceKey === 'requestInstance'
|
||||
? (axiosFetchInstance['requestInstance'] =
|
||||
instance as RequestInterceptorConfig)
|
||||
: (axiosFetchInstance['responseInstance'] =
|
||||
instance as ResponseInterceptorConfig)
|
||||
): void => {
|
||||
if (instanceKey === 'requestInstance') {
|
||||
axiosFetchInstance.requestInstance = instance as RequestInterceptorConfig
|
||||
} else {
|
||||
axiosFetchInstance.responseInstance =
|
||||
instance as ResponseInterceptorConfig
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前实例
|
||||
/**
|
||||
*
|
||||
* @param instanceKey - 实例类型标识
|
||||
*
|
||||
* @returns 对应的实例
|
||||
*
|
||||
* @description
|
||||
* 获取当前实例。
|
||||
*/
|
||||
const getAxiosInstance = (instanceKey: keyof AxiosFetchInstance) => {
|
||||
return axiosFetchInstance[instanceKey]
|
||||
}
|
||||
|
||||
// 设置注入方法队列
|
||||
/**
|
||||
*
|
||||
* @param key - 队列键名
|
||||
* @param func - 拦截器函数数组
|
||||
* @param fetchType - 请求类型(成功/失败)
|
||||
*
|
||||
* @description
|
||||
* 设置注入方法队列。
|
||||
*/
|
||||
const setImplement = (
|
||||
key: ImplementKeys | ErrorImplementKeys,
|
||||
func: AnyFC[],
|
||||
fetchType: FetchType,
|
||||
) => {
|
||||
fetchType === 'ok'
|
||||
? (implement[key as ImplementKeys] = func)
|
||||
: (errorImplement[key as ErrorImplementKeys] = func)
|
||||
): void => {
|
||||
if (fetchType === 'ok') {
|
||||
implement[key as ImplementKeys] = func
|
||||
} else {
|
||||
errorImplement[key as ErrorImplementKeys] = func
|
||||
}
|
||||
}
|
||||
|
||||
// 获取队列中所有的所有拦截器方法
|
||||
/**
|
||||
*
|
||||
* @param key - 队列键名
|
||||
* @param fetchType - 请求类型(成功/失败)
|
||||
*
|
||||
* @returns 拦截器函数数组
|
||||
*
|
||||
* @description
|
||||
* 获取队列中所有的拦截器方法。
|
||||
*/
|
||||
const getImplement = (
|
||||
key: ImplementKeys | ErrorImplementKeys,
|
||||
fetchType: FetchType,
|
||||
@ -80,47 +117,68 @@ export const useAxiosInterceptor = () => {
|
||||
: errorImplement[key as ErrorImplementKeys]
|
||||
}
|
||||
|
||||
// 队列执行器
|
||||
const implementer = (funcs: AnyFC[], ...args: any[]) => {
|
||||
if (Array.isArray(funcs)) {
|
||||
funcs.forEach((curr) => {
|
||||
if (typeof curr === 'function') {
|
||||
curr(...args)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param funcs - 函数数组
|
||||
* @param args - 传递给函数的参数
|
||||
*
|
||||
* @description
|
||||
* 队列执行器 - 执行所有拦截器函数。
|
||||
*/
|
||||
const executeQueue = (funcs: AnyFC[], ...args: unknown[]): void => {
|
||||
funcs.forEach((func) => {
|
||||
if (typeof func === 'function') {
|
||||
func(...args)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 请求、响应前执行拦截器队列中的所有方法
|
||||
/**
|
||||
*
|
||||
* @param key - 实例类型标识
|
||||
* @param implementKey - 队列键名
|
||||
* @param fetchType - 请求类型(成功/失败)
|
||||
*
|
||||
* @description
|
||||
* 请求、响应前执行拦截器队列中的所有方法。
|
||||
*/
|
||||
const beforeFetch = (
|
||||
key: keyof AxiosFetchInstance,
|
||||
implementKey: ImplementKeys | ErrorImplementKeys,
|
||||
fetchType: FetchType,
|
||||
) => {
|
||||
const funcArr =
|
||||
fetchType === 'ok'
|
||||
? implement[implementKey as ImplementKeys]
|
||||
: errorImplement[implementKey as ErrorImplementKeys]
|
||||
): void => {
|
||||
const instance = getAxiosInstance(key)
|
||||
|
||||
if (!instance) {
|
||||
return
|
||||
}
|
||||
|
||||
const funcArr = getImplement(implementKey, fetchType)
|
||||
const { MODE } = getAppEnvironment()
|
||||
|
||||
if (instance) {
|
||||
implementer(funcArr, instance, MODE)
|
||||
}
|
||||
executeQueue(funcArr, instance, MODE)
|
||||
}
|
||||
|
||||
// 请求、响应错误时执行队列中所有方法
|
||||
/**
|
||||
*
|
||||
* @param key - 错误类型标识
|
||||
* @param error - 错误对象
|
||||
* @param errorImplementKey - 错误队列键名
|
||||
*
|
||||
* @description
|
||||
* 请求、响应错误时执行队列中所有方法。
|
||||
*/
|
||||
const fetchError = (
|
||||
key: keyof AxiosFetchError,
|
||||
error: AxiosError<unknown, unknown>,
|
||||
errorImplementKey: ErrorImplementKeys,
|
||||
) => {
|
||||
): void => {
|
||||
axiosFetchError[key] = error
|
||||
|
||||
const funcArr = errorImplement[errorImplementKey]
|
||||
const { MODE } = getAppEnvironment()
|
||||
|
||||
implementer(funcArr, error, MODE)
|
||||
executeQueue(funcArr, error, MODE)
|
||||
}
|
||||
|
||||
return {
|
||||
@ -133,4 +191,4 @@ export const useAxiosInterceptor = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export type UseAxiosInterceptor = ReturnType<typeof useAxiosInterceptor>
|
||||
export type AxiosInterceptor = ReturnType<typeof axiosInterceptor>
|
||||
|
||||
@ -2,7 +2,22 @@ import RBarcode from './src/Barcode'
|
||||
import barcodeProps from './src/props'
|
||||
|
||||
import type { ExtractPublicPropTypes } from 'vue'
|
||||
import type { RBarcodeSize } from './src/types'
|
||||
|
||||
export type BarcodeProps = ExtractPublicPropTypes<typeof barcodeProps>
|
||||
// 扩展 BarcodeProps 以提供更好的类型提示
|
||||
export type BarcodeProps = Omit<
|
||||
ExtractPublicPropTypes<typeof barcodeProps>,
|
||||
'width' | 'height'
|
||||
> & {
|
||||
width?: RBarcodeSize
|
||||
height?: RBarcodeSize
|
||||
}
|
||||
|
||||
export { RBarcode, barcodeProps }
|
||||
|
||||
export type {
|
||||
RBarcodeSize,
|
||||
RBarcodeRender,
|
||||
RBarcodeFormat,
|
||||
RBarcodeOptions,
|
||||
} from './src/types'
|
||||
|
||||
@ -6,8 +6,10 @@ import barcode from 'jsbarcode'
|
||||
import props from './props'
|
||||
import { completeSize, call } from '@/utils'
|
||||
import { useTemplateRef } from 'vue'
|
||||
import { useResizeObserver } from '@vueuse/core'
|
||||
|
||||
import type { WatchStopHandle } from 'vue'
|
||||
import type { UseResizeObserverReturn } from '@vueuse/core'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RBarcode',
|
||||
@ -16,10 +18,25 @@ export default defineComponent({
|
||||
const barcodeRef = useTemplateRef<HTMLCanvasElement | HTMLOrSVGElement>(
|
||||
'barcodeRef',
|
||||
)
|
||||
const containerRef = useTemplateRef<HTMLDivElement>('containerRef')
|
||||
const containerSize = ref({ width: 0, height: 0 })
|
||||
let resizeObserverReturn: UseResizeObserverReturn | null
|
||||
|
||||
const cssVars = computed(() => {
|
||||
let width = completeSize(props.width)
|
||||
let height = completeSize(props.height)
|
||||
|
||||
if (props.width === 'responsive' && containerSize.value.width > 0) {
|
||||
width = `${containerSize.value.width}px`
|
||||
}
|
||||
|
||||
if (props.height === 'responsive' && containerSize.value.height > 0) {
|
||||
height = `${containerSize.value.height}px`
|
||||
}
|
||||
|
||||
const cssVar = {
|
||||
'--r-barcode-width': completeSize(props.width),
|
||||
'--r-barcode-height': completeSize(props.height),
|
||||
'--r-barcode-width': width,
|
||||
'--r-barcode-height': height,
|
||||
}
|
||||
|
||||
return cssVar
|
||||
@ -27,6 +44,10 @@ export default defineComponent({
|
||||
let watchStop: WatchStopHandle
|
||||
|
||||
const barcodeRender = () => {
|
||||
if (!barcodeRef.value) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const { format, text, options, onSuccess } = props
|
||||
|
||||
@ -34,6 +55,20 @@ export default defineComponent({
|
||||
format,
|
||||
})
|
||||
|
||||
// 如果是响应式模式,根据容器尺寸调整条形码选项
|
||||
if (containerSize.value.width > 0) {
|
||||
if (props.width === 'responsive') {
|
||||
assignOptions.width = Math.max(1, containerSize.value.width / 100)
|
||||
}
|
||||
|
||||
if (props.height === 'responsive') {
|
||||
assignOptions.height = Math.max(
|
||||
20,
|
||||
containerSize.value.height * 0.8,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
barcode(
|
||||
barcodeRef.value,
|
||||
text !== void 0 && text !== null ? text.toString() : '',
|
||||
@ -60,14 +95,51 @@ export default defineComponent({
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.watchText) {
|
||||
watchStop?.()
|
||||
|
||||
watchStop = watch(() => props.text, barcodeRender)
|
||||
} else {
|
||||
watchStop?.()
|
||||
}
|
||||
|
||||
// 监听容器尺寸变化
|
||||
if (props.responsive) {
|
||||
resizeObserverReturn?.stop()
|
||||
|
||||
resizeObserverReturn = useResizeObserver(
|
||||
containerRef,
|
||||
(entries: readonly ResizeObserverEntry[]) => {
|
||||
const entry = entries[0]
|
||||
|
||||
if (entry) {
|
||||
const { width, height } = entry.contentRect
|
||||
|
||||
containerSize.value = { width, height }
|
||||
|
||||
nextTick(() => {
|
||||
barcodeRender()
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
resizeObserverReturn?.stop()
|
||||
|
||||
resizeObserverReturn = null
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
barcodeRender()
|
||||
// 初始化容器尺寸
|
||||
if (containerRef.value) {
|
||||
const rect = containerRef.value.getBoundingClientRect()
|
||||
|
||||
containerSize.value = { width: rect.width, height: rect.height }
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
barcodeRender()
|
||||
})
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
watchStop?.()
|
||||
@ -75,11 +147,12 @@ export default defineComponent({
|
||||
|
||||
return {
|
||||
barcodeRef,
|
||||
containerRef,
|
||||
cssVars,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { barcodeRender, loading, cssVars } = this
|
||||
const { barcodeRender, loading, cssVars, responsive } = this
|
||||
const c = [
|
||||
'r-barcode',
|
||||
{
|
||||
@ -87,12 +160,21 @@ export default defineComponent({
|
||||
},
|
||||
]
|
||||
|
||||
const barcodeElement =
|
||||
barcodeRender === 'canvas' ? (
|
||||
<canvas class={c} style={cssVars} ref="barcodeRef" />
|
||||
) : (
|
||||
<svg class={c} style={cssVars} ref="barcodeRef" />
|
||||
)
|
||||
|
||||
return (
|
||||
<NSpin class="r-barcode-spin" show={loading}>
|
||||
{barcodeRender === 'canvas' ? (
|
||||
<canvas class={c} style={cssVars} ref="barcodeRef" />
|
||||
{responsive ? (
|
||||
<div class="r-barcode-container" ref="containerRef">
|
||||
{barcodeElement}
|
||||
</div>
|
||||
) : (
|
||||
<svg class={c} style={cssVars} ref="barcodeRef" />
|
||||
barcodeElement
|
||||
)}
|
||||
</NSpin>
|
||||
)
|
||||
|
||||
@ -9,8 +9,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
.r-barcode-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.r-barcode {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.r-barcode-spin,
|
||||
.r-barcode-spin .n-spin-content {
|
||||
width: max-content !important;
|
||||
height: max-content !important;
|
||||
}
|
||||
|
||||
.r-barcode-spin:has(.r-barcode-container),
|
||||
.r-barcode-spin:has(.r-barcode-container) .n-spin-content {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import type { RBarcodeRender, RBarcodeOptions, RBarcodeFormat } from './types'
|
||||
import type {
|
||||
RBarcodeRender,
|
||||
RBarcodeOptions,
|
||||
RBarcodeFormat,
|
||||
RBarcodeSize,
|
||||
} from './types'
|
||||
import type { PropType } from 'vue'
|
||||
import type { MaybeArray } from '@/types'
|
||||
|
||||
@ -7,23 +12,39 @@ const props = {
|
||||
*
|
||||
* @description
|
||||
* 条形码宽度。
|
||||
* - 数字:固定宽度(单位:px)
|
||||
* - 'auto':自动宽度
|
||||
* - 其他字符串:CSS 宽度值(如 '100%', '200px')
|
||||
*
|
||||
* @default 'auto'
|
||||
* @example
|
||||
* width={200}
|
||||
* width="auto"
|
||||
* width="responsive"
|
||||
* width="100%"
|
||||
*/
|
||||
width: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
default: 'auto',
|
||||
type: [String, Number] as PropType<RBarcodeSize>,
|
||||
default: 'auto' as const,
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 条形码高度。
|
||||
* - 数字:固定高度(单位:px)
|
||||
* - 'auto':自动高度
|
||||
* - 其他字符串:CSS 高度值(如 '100%', '200px')
|
||||
*
|
||||
* @default 'auto'
|
||||
* @example
|
||||
* height={100}
|
||||
* height="auto"
|
||||
* height="responsive"
|
||||
* height="50%"
|
||||
*/
|
||||
height: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
default: 'auto',
|
||||
type: [String, Number] as PropType<RBarcodeSize>,
|
||||
default: 'auto' as const,
|
||||
},
|
||||
/**
|
||||
*
|
||||
@ -132,6 +153,19 @@ const props = {
|
||||
onFinally: {
|
||||
type: [Function, Array] as PropType<MaybeArray<() => void>>,
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 是否启用响应式尺寸,当容器大小变化时自动重新渲染条形码。
|
||||
*
|
||||
* 如果启用了该属性,width 和 height 配置项将失效。
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
responsive: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
} as const
|
||||
|
||||
export default props
|
||||
|
||||
@ -24,3 +24,6 @@ export type RBarcodeFormat =
|
||||
| 'MSI1110'
|
||||
| 'pharmacode'
|
||||
| 'codabar'
|
||||
|
||||
// 使用模板字面量类型来保留字面量提示
|
||||
export type RBarcodeSize = number | 'auto' | (string & {})
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import RChart from './src'
|
||||
import RChart from './src/Chart'
|
||||
import chartProps from './src/props'
|
||||
import useChart from './src/hooks/useChart'
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ export default defineComponent({
|
||||
setup(props, { expose }) {
|
||||
const { getAppTheme } = useSettingGetters()
|
||||
// echart 容器实例
|
||||
const rayChartRef = useTemplateRef<HTMLElement>('rayChartRef')
|
||||
const chartRef = useTemplateRef<HTMLElement>('chartRef')
|
||||
// echart 父容器实例
|
||||
const rayChartWrapperRef = useTemplateRef<HTMLElement>('rayChartWrapperRef')
|
||||
// echart 实例
|
||||
@ -113,8 +113,8 @@ export default defineComponent({
|
||||
])
|
||||
const cssVarsRef = computed(() => {
|
||||
return {
|
||||
'--ray-chart-width': completeSize(props.width),
|
||||
'--ray-chart-height': completeSize(props.height),
|
||||
'--r-chart-width': completeSize(props.width),
|
||||
'--r-chart-height': completeSize(props.height),
|
||||
}
|
||||
})
|
||||
// 目标是否可见
|
||||
@ -241,7 +241,7 @@ export default defineComponent({
|
||||
*/
|
||||
const renderChart = (theme: string = echartTheme) => {
|
||||
// 获取 dom 容器
|
||||
const element = rayChartRef.value as HTMLElement
|
||||
const element = chartRef.value as HTMLElement
|
||||
// 获取配置项
|
||||
const options = combineChartOptions(props.options)
|
||||
// 获取 dom 容器实际宽高
|
||||
@ -264,7 +264,7 @@ export default defineComponent({
|
||||
|
||||
// 是否强制下一队列渲染图表
|
||||
if (props.nextTick) {
|
||||
echartInstanceRef.value.setOption({})
|
||||
// echartInstanceRef.value.setOption({})
|
||||
|
||||
nextTick(() => {
|
||||
options && echartInstanceRef.value?.setOption(options)
|
||||
@ -435,6 +435,8 @@ export default defineComponent({
|
||||
watchEffect(() => {
|
||||
// 是否启用了可视区域监听
|
||||
if (props.intersectionObserver) {
|
||||
intersectionObserverReturn?.stop()
|
||||
|
||||
intersectionObserverReturn = useIntersectionObserver(
|
||||
props.intersectionObserverTarget || rayChartWrapperRef,
|
||||
([entry]) => {
|
||||
@ -442,10 +444,14 @@ export default defineComponent({
|
||||
},
|
||||
props.intersectionOptions,
|
||||
)
|
||||
} else {
|
||||
intersectionObserverReturn?.stop()
|
||||
}
|
||||
|
||||
// 监听 options 变化
|
||||
if (props.watchOptions) {
|
||||
watchThrottledCallback?.()
|
||||
|
||||
watchThrottledCallback = watchThrottled(
|
||||
() => props.options,
|
||||
(ndata) => {
|
||||
@ -462,7 +468,7 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
// 深度监听 options
|
||||
deep: true,
|
||||
deep: props.watchDeep,
|
||||
throttle: props.watchOptionsThrottleWait,
|
||||
},
|
||||
)
|
||||
@ -506,7 +512,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
rayChartRef,
|
||||
chartRef,
|
||||
cssVarsRef,
|
||||
rayChartWrapperRef,
|
||||
moreDropDownOptions,
|
||||
@ -536,7 +542,7 @@ export default defineComponent({
|
||||
>
|
||||
{{
|
||||
default: renderNode(
|
||||
<div class="ray-chart__container" ref="rayChartRef"></div>,
|
||||
<div class="ray-chart__container" ref="chartRef"></div>,
|
||||
),
|
||||
header: renderNode(title, {
|
||||
defaultElement: <div style="display: none;"></div>,
|
||||
@ -557,7 +563,7 @@ export default defineComponent({
|
||||
</NCard>
|
||||
) : (
|
||||
<div class="ray-chart" style={[this.cssVarsRef]} ref="rayChartWrapperRef">
|
||||
<div class="ray-chart__container" ref="rayChartRef"></div>
|
||||
<div class="ray-chart__container" ref="chartRef"></div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@ -1,6 +1,6 @@
|
||||
.ray-chart {
|
||||
width: var(--ray-chart-width);
|
||||
height: var(--ray-chart-height);
|
||||
width: var(--r-chart-width);
|
||||
height: var(--r-chart-height);
|
||||
border: none;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
|
||||
@ -341,6 +341,17 @@ const props = {
|
||||
type: Number,
|
||||
default: 500,
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 是否深度监听 options 配置项。
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
watchDeep: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import RIcon from './src'
|
||||
import RIcon from './src/Icon'
|
||||
import iconProps from './src/props'
|
||||
|
||||
import type { ExtractPublicPropTypes } from 'vue'
|
||||
|
||||
@ -10,15 +10,15 @@ export default defineComponent({
|
||||
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
|
||||
const cssVars = computed(() => {
|
||||
const cssVar = {
|
||||
'--ray-icon-width': props.width
|
||||
'--r-icon-width': props.width
|
||||
? completeSize(props.width)
|
||||
: completeSize(props.size),
|
||||
'--ray-icon-height': props.height
|
||||
'--r-icon-height': props.height
|
||||
? completeSize(props.height)
|
||||
: completeSize(props.size),
|
||||
'--ray-icon-depth': props.depth,
|
||||
'--ray-icon-cursor': props.cursor,
|
||||
'--ray-icon-color': props.color,
|
||||
'--r-icon-depth': props.depth,
|
||||
'--r-icon-cursor': props.cursor,
|
||||
'--r-icon-color': props.color,
|
||||
}
|
||||
|
||||
return cssVar
|
||||
@ -41,13 +41,13 @@ export default defineComponent({
|
||||
render() {
|
||||
return (
|
||||
<span
|
||||
class={['ray-icon', this.customClassName]}
|
||||
class={['r-icon', this.customClassName]}
|
||||
style={[this.cssVars]}
|
||||
onClick={this.iconClick.bind(this)}
|
||||
onClick={this.iconClick}
|
||||
>
|
||||
<svg
|
||||
{...({
|
||||
RayIconAttribute: 'ray-icon',
|
||||
RIconAttribute: 'r-icon',
|
||||
ariaHidden: true,
|
||||
} as object)}
|
||||
>
|
||||
@ -1,28 +1,28 @@
|
||||
.ray-icon {
|
||||
.r-icon {
|
||||
position: relative;
|
||||
width: var(--ray-icon-width);
|
||||
height: var(--ray-icon-height);
|
||||
width: var(--r-icon-width);
|
||||
height: var(--r-icon-height);
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--ray-icon-color);
|
||||
color: var(--r-icon-color);
|
||||
transform: translateZ(0);
|
||||
opacity: var(--ray-icon-depth);
|
||||
cursor: var(--ray-icon-cursor);
|
||||
opacity: var(--r-icon-depth);
|
||||
cursor: var(--r-icon-cursor);
|
||||
|
||||
& svg[RayIconAttribute='ray-icon'] {
|
||||
width: var(--ray-icon-width);
|
||||
height: var(--ray-icon-height);
|
||||
& svg[RIconAttribute='r-icon'] {
|
||||
width: var(--r-icon-width);
|
||||
height: var(--r-icon-height);
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.ray-icon-path__animate {
|
||||
stroke-dasharray: var(--ray-icon-path-length);
|
||||
stroke-dashoffset: var(--ray-icon-path-length);
|
||||
.r-icon-path__animate {
|
||||
stroke-dasharray: var(--r-icon-path-length);
|
||||
stroke-dashoffset: var(--r-icon-path-length);
|
||||
animation: rayIconPathAnimate 2s forwards;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import RIframe from './src'
|
||||
import RIframe from './src/Iframe'
|
||||
import iframeProps from './src/props'
|
||||
|
||||
import type * as RIframeType from './src/types'
|
||||
|
||||
@ -13,9 +13,9 @@ export default defineComponent({
|
||||
setup(props, { expose }) {
|
||||
const cssVars = computed(() => {
|
||||
const cssVar = {
|
||||
'--ray-iframe-frameborder': completeSize(props.frameborder),
|
||||
'--ray-iframe-width': completeSize(props.width),
|
||||
'--ray-iframe-height': completeSize(props.height),
|
||||
'--r-iframe-frameborder': completeSize(props.frameborder),
|
||||
'--r-iframe-width': completeSize(props.width),
|
||||
'--r-iframe-height': completeSize(props.height),
|
||||
}
|
||||
|
||||
return cssVar
|
||||
@ -1,8 +1,8 @@
|
||||
.ray-iframe {
|
||||
width: var(--ray-iframe-width);
|
||||
height: var(--ray-iframe-height);
|
||||
width: var(--r-iframe-width);
|
||||
height: var(--r-iframe-height);
|
||||
box-sizing: border-box;
|
||||
border: var(--ray-iframe-frameborder);
|
||||
border: var(--r-iframe-frameborder);
|
||||
|
||||
& .ray-iframe__container {
|
||||
width: 100%;
|
||||
|
||||
@ -4,6 +4,15 @@ import { R_MODAL_CLASS, CSS_VARS_KEYS } from '../constant'
|
||||
|
||||
import type { RModalProps } from '../types'
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @see https://www.naiveui.com/zh-CN/dark/components/modal#useModal-API
|
||||
*
|
||||
* @description
|
||||
* 请使用官方的 `useModal` 方法。
|
||||
*/
|
||||
const useModal = () => {
|
||||
const { create: naiveCreate, destroyAll: naiveDestroyAll } = useNaiveModal()
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import RMoreDropdown from './src'
|
||||
import RMoreDropdown from './src/MoreDropdown'
|
||||
import moreDropdownProps from './src/props'
|
||||
|
||||
import type { ExtractPublicPropTypes } from 'vue'
|
||||
|
||||
@ -13,27 +13,25 @@ import { config } from './shared'
|
||||
import { pick } from 'lodash-es'
|
||||
import { useTemplateRef } from 'vue'
|
||||
|
||||
import type { DropdownOption, DataTableInst, DataTableProps } from 'naive-ui'
|
||||
import type { DropdownOption, DataTableProps } from 'naive-ui'
|
||||
import type { ComponentSize } from '@/types'
|
||||
import type {
|
||||
C as CType,
|
||||
PropsComponentPopselectKeys,
|
||||
RTableInst,
|
||||
} from './types'
|
||||
import type { ExtractPublicPropTypes } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RTable',
|
||||
inheritAttrs: false,
|
||||
props,
|
||||
setup(props, ctx) {
|
||||
const { expose, emit } = ctx
|
||||
const { expose } = ctx
|
||||
|
||||
const rTableInst = useTemplateRef<RTableInst>('rTableInst')
|
||||
const wrapperRef = useTemplateRef<HTMLElement>('wrapperRef')
|
||||
|
||||
const uuidWrapper = uuid(16) // wrapper id
|
||||
const uuidTable = uuid(16) // table id
|
||||
const uuidWrapper = uuid(16)
|
||||
const uuidTable = uuid(16)
|
||||
/**
|
||||
*
|
||||
* x: 横坐标
|
||||
@ -94,53 +92,70 @@ export default defineComponent({
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key key
|
||||
* @param option context menu select option
|
||||
* @param key 当前选中项的 key
|
||||
* @param option 当前选中项
|
||||
*
|
||||
* @description
|
||||
* 右键菜单选择事件回调。
|
||||
*/
|
||||
const contextMenuSelect = (
|
||||
key: number | string,
|
||||
option: DropdownOption,
|
||||
) => {
|
||||
contextMenuReactive.showContextMenu = false
|
||||
|
||||
const { onContextMenuClick } = props
|
||||
|
||||
if (onContextMenuClick) {
|
||||
call(onContextMenuClick, key, option)
|
||||
}
|
||||
|
||||
contextMenuReactive.showContextMenu = false
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 合并 RTable 的所有 rowProps
|
||||
* 如果开启了右键菜单功能,自动会拦截右键事件
|
||||
* @param e 鼠标点击事件
|
||||
*
|
||||
* @description
|
||||
* 处理右键菜单事件。
|
||||
*/
|
||||
const tableContextMenu = (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
contextMenuReactive.showContextMenu = false
|
||||
|
||||
nextTick().then(() => {
|
||||
contextMenuReactive.showContextMenu = true
|
||||
contextMenuReactive.x = e.clientX
|
||||
contextMenuReactive.y = e.clientY
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param row 当前行数据
|
||||
* @param idx 当前行索引
|
||||
*
|
||||
* @description
|
||||
* 合并 RTable 的所有 rowProps,如果开启了右键菜单功能,自动会拦截右键事件。
|
||||
*/
|
||||
const combineRowProps = (row: Record<string, unknown>, idx: number) => {
|
||||
const interceptRowProps = props.rowProps?.(row, idx)
|
||||
const interceptRowProps = props.rowProps?.(row, idx) || {}
|
||||
|
||||
if (props.disabledContextMenu) {
|
||||
return interceptRowProps
|
||||
}
|
||||
|
||||
return {
|
||||
...interceptRowProps,
|
||||
onContextmenu: props.disabledContextMenu
|
||||
? void 0
|
||||
: (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
contextMenuReactive.showContextMenu = false
|
||||
|
||||
nextTick().then(() => {
|
||||
contextMenuReactive.showContextMenu = true
|
||||
contextMenuReactive.x = e.clientX
|
||||
contextMenuReactive.y = e.clientY
|
||||
})
|
||||
},
|
||||
onContextmenu: tableContextMenu,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param size table size
|
||||
* @param size 表格尺寸
|
||||
*
|
||||
* 修改 table size
|
||||
* @description
|
||||
* 修改表格尺寸。
|
||||
*/
|
||||
const changeTableSize = (size: ComponentSize) => {
|
||||
privateReactive.size = size
|
||||
@ -148,9 +163,10 @@ export default defineComponent({
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options table columns
|
||||
* @param options 表格列配置项
|
||||
*
|
||||
* 更新 table columns,同时触发 onUpdateColumns 和 onUpdate:columns 事件
|
||||
* @description
|
||||
* 更新 table columns,同时触发 onUpdateColumns 和 onUpdate:columns 事件。
|
||||
*/
|
||||
const updateTableColumn = (options: CType[]) => {
|
||||
const { onUpdateColumns, 'onUpdate:columns': $onUpdateColumns } = props
|
||||
@ -166,8 +182,9 @@ export default defineComponent({
|
||||
|
||||
/**
|
||||
*
|
||||
* 处理自定义的 toolOptions
|
||||
* 匹配所有符合条件的 toolOptions,然后执行
|
||||
* @description
|
||||
* 处理自定义的 toolOptions。
|
||||
* 匹配所有符合条件的 toolOptions,然后执行。
|
||||
*/
|
||||
const renderToolOptions = () => {
|
||||
const { toolOptions } = props
|
||||
@ -189,45 +206,56 @@ export default defineComponent({
|
||||
|
||||
/**
|
||||
*
|
||||
* @param p props
|
||||
*
|
||||
* 处理 toolOptions,合并渲染所有的 toolOptions
|
||||
* @description
|
||||
* 渲染默认工具栏。
|
||||
*/
|
||||
const tool = (p: typeof props) => {
|
||||
const { tool } = p
|
||||
const renderDefaultToolOptions = () => {
|
||||
const { onUpdateColumns, 'onUpdate:columns': rOnUpdateColumns } = props
|
||||
const needSettingComponent = !!onUpdateColumns || !!rOnUpdateColumns
|
||||
|
||||
if (!tool) {
|
||||
return
|
||||
}
|
||||
|
||||
const renderDefaultToolOptions = () => (
|
||||
return (
|
||||
<NFlex align="center">
|
||||
<Print {...p} />
|
||||
<Size {...p} onChangeSize={changeTableSize.bind(this)} />
|
||||
<Print {...props} />
|
||||
<Size {...props} onChangeSize={changeTableSize} />
|
||||
<Fullscreen />
|
||||
<C {...p} onUpdateColumn={updateTableColumn.bind(this)} />
|
||||
{needSettingComponent ? (
|
||||
<C {...props} onUpdateColumn={updateTableColumn} />
|
||||
) : null}
|
||||
<TablePropsSelect
|
||||
{...p}
|
||||
onPopselectChange={popselectChange.bind(this)}
|
||||
onInitialed={popselectChange.bind(this)}
|
||||
{...props}
|
||||
onPopselectChange={popselectChange}
|
||||
onInitialed={popselectChange}
|
||||
/>
|
||||
</NFlex>
|
||||
)
|
||||
}
|
||||
|
||||
if (!props.toolOptions) {
|
||||
return renderDefaultToolOptions
|
||||
} else {
|
||||
if (props.coverTool) {
|
||||
return () => <NFlex align="center">{renderToolOptions()}</NFlex>
|
||||
} else {
|
||||
return () => (
|
||||
<NFlex align="center">
|
||||
{renderDefaultToolOptions()}
|
||||
{renderToolOptions()}
|
||||
</NFlex>
|
||||
)
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param p props
|
||||
*
|
||||
* @description
|
||||
* 处理 toolOptions,合并渲染所有的 toolOptions。
|
||||
*/
|
||||
const tool = (p: typeof props) => {
|
||||
if (!p.tool) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!p.toolOptions) {
|
||||
return renderDefaultToolOptions
|
||||
}
|
||||
|
||||
if (p.coverTool) {
|
||||
return () => <NFlex align="center">{renderToolOptions()}</NFlex>
|
||||
}
|
||||
|
||||
return () => (
|
||||
<NFlex align="center">
|
||||
{renderDefaultToolOptions()}
|
||||
{renderToolOptions()}
|
||||
</NFlex>
|
||||
)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -239,6 +267,7 @@ export default defineComponent({
|
||||
uuidTable,
|
||||
uuidWrapper,
|
||||
wrapperRef,
|
||||
tableRef: rTableInst,
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -263,6 +292,7 @@ export default defineComponent({
|
||||
propsPopselectValue,
|
||||
cardHeaderStyle,
|
||||
flexAutoHeightStyle,
|
||||
tableContextMenu,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
|
||||
@ -177,7 +177,10 @@ export default defineComponent({
|
||||
const { onUpdateColumn } = props
|
||||
|
||||
if (onUpdateColumn) {
|
||||
call(onUpdateColumn, options)
|
||||
// 使用 nextTick 确保 DOM 更新后再触发事件
|
||||
nextTick(() => {
|
||||
call(onUpdateColumn, options)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -303,6 +303,43 @@ const useCheckedRowKeys = <
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param keys 批量选中的 keys
|
||||
*
|
||||
* @description
|
||||
* 批量选中指定的 keys。
|
||||
*/
|
||||
const selectKeys = (keys: RowKey[]) => {
|
||||
keys.forEach((key) => selectKey(key))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key 需要切换的 key
|
||||
*
|
||||
* @description
|
||||
* 切换指定 key 的选中状态。
|
||||
*/
|
||||
const toggleKey = (key: RowKey) => {
|
||||
if (keysRef.value.includes(key)) {
|
||||
clearKey(key)
|
||||
} else {
|
||||
selectKey(key)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key 需要检查的 key
|
||||
*
|
||||
* @description
|
||||
* 检查指定 key 是否被选中。
|
||||
*/
|
||||
const isKeySelected = (key: RowKey) => {
|
||||
return keysRef.value.includes(key)
|
||||
}
|
||||
|
||||
effectDispose(() => {
|
||||
clearAll()
|
||||
})
|
||||
@ -317,6 +354,9 @@ const useCheckedRowKeys = <
|
||||
clearAll,
|
||||
clearKey,
|
||||
selectKey,
|
||||
selectKeys,
|
||||
toggleKey,
|
||||
isKeySelected,
|
||||
},
|
||||
] as const
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
& .ray-icon {
|
||||
& .r-icon {
|
||||
&.r-table__c-tool-icon--active {
|
||||
color: var(--ray-theme-primary-color);
|
||||
color: var(--r-theme-primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ export interface TableProvider {
|
||||
uuidWrapper: string
|
||||
uuidTable: string
|
||||
wrapperRef: Readonly<ShallowRef<HTMLElement | null>>
|
||||
tableRef: Readonly<ShallowRef<RTableInst | null>>
|
||||
}
|
||||
|
||||
export interface C extends DataTableBaseColumn {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import RTransitionComponent from './src/index.vue'
|
||||
import RTransitionComponent from './src/TransitionComponent.vue'
|
||||
import transitionComponentProps from './src/props'
|
||||
|
||||
import type * as RTransitionComponentType from './src/types'
|
||||
|
||||
@ -9,12 +9,14 @@ import { omit } from 'lodash-es'
|
||||
|
||||
import type { TablePagination, TableRequestConfig, TableProInst } from './types'
|
||||
import type { RTableInst } from '../../..'
|
||||
import type { Recordable } from '@/types'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RTablePro',
|
||||
props,
|
||||
setup(props, ctx) {
|
||||
const { expose } = ctx
|
||||
|
||||
const [register, tableFns] = useTable()
|
||||
const [
|
||||
paginationRef,
|
||||
@ -31,58 +33,53 @@ export default defineComponent({
|
||||
] = usePagination(void 0, {
|
||||
prefix: props.paginationPrefix,
|
||||
})
|
||||
const tableRequestRef = computed(() => props.request)
|
||||
|
||||
// 获取最新 statistics 和 pagination 值
|
||||
const update = (): TablePagination => {
|
||||
const page = getPage()
|
||||
const pageSize = getPageSize()
|
||||
const itemCount = getItemCount()
|
||||
|
||||
return {
|
||||
page,
|
||||
pageSize,
|
||||
itemCount,
|
||||
}
|
||||
}
|
||||
// 获取最新 pagination 值 - 使用 computed 避免函数重新创建
|
||||
const tablePagination = computed<TablePagination>(() => ({
|
||||
page: getPage(),
|
||||
pageSize: getPageSize(),
|
||||
itemCount: getItemCount(),
|
||||
}))
|
||||
|
||||
// 派发表格更新事件
|
||||
const emitTableUpdate = () => {
|
||||
const { onTablePaginationUpdate } = props
|
||||
|
||||
if (onTablePaginationUpdate) {
|
||||
call(onTablePaginationUpdate, update())
|
||||
call(onTablePaginationUpdate, tablePagination.value)
|
||||
}
|
||||
}
|
||||
|
||||
// 合并请求参数
|
||||
const combineRequestParams = (extraConfig?: TableRequestConfig) => {
|
||||
const combineRequestParams = <T extends Recordable>(
|
||||
extraConfig?: TableRequestConfig<T>,
|
||||
) => {
|
||||
const config = Object.assign({}, props.requestConfig, extraConfig)
|
||||
|
||||
const { formatRangeTime, excludeParams } = config
|
||||
let params = config.params || {}
|
||||
const {
|
||||
formatRangeTime,
|
||||
excludeParams,
|
||||
autoDeleteDuplicateKeys = true,
|
||||
} = config
|
||||
let params: Recordable = config.params || {}
|
||||
|
||||
// 转换时间范围,该功能仅支持 NDatePicker range 模式参数
|
||||
if (formatRangeTime?.length && params) {
|
||||
formatRangeTime.forEach((curr) => {
|
||||
const { key, target } = curr
|
||||
formatRangeTime.forEach(({ key, target }) => {
|
||||
const val = params[key] as [number, number] | null
|
||||
|
||||
if (val && target?.length) {
|
||||
const [start, end] = val
|
||||
|
||||
params[target[0]] = start
|
||||
params[target[1]] = end
|
||||
} else {
|
||||
// 当传递时间参数被清空时,则清空对应 time key
|
||||
params[key] = null
|
||||
params[target[0]] = null
|
||||
params[target[1]] = null
|
||||
if (val && target?.length === 2) {
|
||||
params[target[0]] = val[0]
|
||||
params[target[1]] = val[1]
|
||||
}
|
||||
|
||||
// 清空时间参数的 key
|
||||
delete params[key]
|
||||
})
|
||||
}
|
||||
|
||||
params = removeDuplicateKeys(params)
|
||||
if (autoDeleteDuplicateKeys) {
|
||||
params = removeDuplicateKeys(params)
|
||||
}
|
||||
|
||||
// 排除指定的请求参数
|
||||
if (excludeParams) {
|
||||
@ -94,10 +91,10 @@ export default defineComponent({
|
||||
pageSize: getPageSize(),
|
||||
})
|
||||
|
||||
return requestParams
|
||||
return requestParams as T & { page: number; pageSize: number }
|
||||
}
|
||||
|
||||
// 同步执行 request 请求,允许重置 pagination 请求,返回 Promise 对象
|
||||
// 同步执行 request 请求,允许重置 pagination 请求
|
||||
const runResetPaginationRequest: TableProInst['runTableRequest'] = (
|
||||
extraConfig,
|
||||
reset = true,
|
||||
@ -108,21 +105,19 @@ export default defineComponent({
|
||||
|
||||
const requestParams = combineRequestParams(extraConfig)
|
||||
|
||||
tableRequestRef.value?.(requestParams)
|
||||
props.request?.(requestParams)
|
||||
}
|
||||
|
||||
// 异步执行 request 请求,允许重置 pagination 请求,返回 Promise 对象
|
||||
const runResetPaginationRequestAsync: TableProInst['runAsyncTableRequest'] =
|
||||
(extraConfig, reset = true) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
runResetPaginationRequest(extraConfig, reset)
|
||||
async (extraConfig, reset = true) => {
|
||||
if (reset) {
|
||||
resetPagination()
|
||||
}
|
||||
|
||||
resolve(void 0)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
const requestParams = combineRequestParams(extraConfig)
|
||||
|
||||
await props.request?.(requestParams)
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
@ -144,7 +139,7 @@ export default defineComponent({
|
||||
if (onRegister) {
|
||||
call(onRegister, {
|
||||
...(tableFns as unknown as RTableInst),
|
||||
getTablePagination: update,
|
||||
getTablePagination: () => tablePagination.value,
|
||||
runTableRequest: runResetPaginationRequest,
|
||||
runAsyncTableRequest: runResetPaginationRequestAsync,
|
||||
getCurrentTableRequestParams: combineRequestParams,
|
||||
@ -156,6 +151,7 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
expose()
|
||||
|
||||
return {
|
||||
@ -172,37 +168,23 @@ export default defineComponent({
|
||||
flexAutoHeight,
|
||||
...rest
|
||||
} = $props
|
||||
const { collapse, ...restSlots } = $slots
|
||||
const baseProps = {
|
||||
onRegister: register,
|
||||
pagination: showPagination ? paginationRef : void 0,
|
||||
flexAutoHeight: takeoverAutoHeight || flexAutoHeight,
|
||||
...rest,
|
||||
}
|
||||
const { collapse, ...restSlots } = $slots
|
||||
|
||||
if (takeoverAutoHeight) {
|
||||
return (
|
||||
<NFlex vertical class="flex-vertical">
|
||||
{{
|
||||
default: () => (
|
||||
<>
|
||||
{collapse?.()}
|
||||
<RTable {...baseProps} {...rest} flexAutoHeight>
|
||||
{{
|
||||
...restSlots,
|
||||
}}
|
||||
</RTable>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
<NFlex vertical class="h-full">
|
||||
{collapse?.()}
|
||||
<RTable {...baseProps}>{restSlots}</RTable>
|
||||
</NFlex>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<RTable {...baseProps} {...rest} flexAutoHeight={flexAutoHeight}>
|
||||
{{
|
||||
...restSlots,
|
||||
}}
|
||||
</RTable>
|
||||
)
|
||||
}
|
||||
|
||||
return <RTable {...baseProps}>{restSlots}</RTable>
|
||||
},
|
||||
})
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { printDom } from '@/utils'
|
||||
|
||||
import type { Recordable } from '@/types'
|
||||
import type { TableProInst, TableRequestConfig } from '../types'
|
||||
import type {
|
||||
@ -156,16 +154,8 @@ export const useTablePro = () => {
|
||||
* @description
|
||||
* 打印表格。
|
||||
*/
|
||||
const print = (options?: PrintDomOptions) => {
|
||||
const { config } = getTableProInstance()
|
||||
const { uuidWrapper } = config ?? {}
|
||||
|
||||
if (uuidWrapper) {
|
||||
const tableWrapperElement = document.getElementById(uuidWrapper)
|
||||
|
||||
printDom(tableWrapperElement, options)
|
||||
}
|
||||
}
|
||||
const print = (options?: PrintDomOptions) =>
|
||||
getTableProInstance().print.call(null, options)
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@ -30,7 +30,9 @@ export interface BasePagination {
|
||||
*/
|
||||
export type TablePagination = BasePagination
|
||||
|
||||
export type TablePaginationUpdate = (pagination: TablePagination) => void
|
||||
export type TablePaginationUpdate = (
|
||||
pagination: Readonly<TablePagination>,
|
||||
) => void
|
||||
|
||||
export type PaginationPrefix = UsePaginationOptions['prefix']
|
||||
|
||||
@ -63,6 +65,14 @@ export interface TableRequestConfig<
|
||||
* @default undefined
|
||||
*/
|
||||
excludeParams?: ExcludeParams[]
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 是否自动移除重复的请求参数。
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
autoDeleteDuplicateKeys?: boolean
|
||||
}
|
||||
|
||||
export type TableProProps = Omit<TableProps, 'pagination'>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { setVariable, getVariableToRefs } from '@/global-variable'
|
||||
import { LAYOUT_CONTENT_REF } from '@/app-config'
|
||||
import { unrefElement } from '@/utils'
|
||||
import { useElementFullscreen } from '../web'
|
||||
|
||||
import type { UseElementFullscreenOptions } from '../web'
|
||||
@ -24,7 +23,13 @@ export interface MaximizeOptions extends UseElementFullscreenOptions {
|
||||
scrollToOptions?: ScrollToOptions
|
||||
}
|
||||
|
||||
export const useMaximize = () => {
|
||||
export const useMaximize = (options?: MaximizeOptions) => {
|
||||
const contentEl = LAYOUT_CONTENT_REF as Ref<HTMLElement>
|
||||
const { enter, exit, toggleFullscreen, isFullscreen } = useElementFullscreen(
|
||||
contentEl,
|
||||
options,
|
||||
)
|
||||
|
||||
/**
|
||||
*
|
||||
* 当前 LayoutContent 是处于否全屏状态
|
||||
@ -46,25 +51,30 @@ export const useMaximize = () => {
|
||||
* 该方法仅针对于 LayoutContent 区域,并且依赖全局属性 layoutContentMaximize。
|
||||
*
|
||||
* @example
|
||||
* maximize(true, { MaximizeOptions }) 全屏内容区域
|
||||
* maximize(false, { MaximizeOptions }) 取消全屏内容区域
|
||||
* maximize(true) 全屏内容区域
|
||||
* maximize(false) 取消全屏内容区域
|
||||
*/
|
||||
const maximize = (full: boolean, options?: MaximizeOptions) => {
|
||||
const { scrollToOptions } = options ?? {}
|
||||
const contentEl = unrefElement(LAYOUT_CONTENT_REF as Ref<HTMLElement>)
|
||||
const { toggleFullscreen } = useElementFullscreen(contentEl, options)
|
||||
|
||||
setVariable('layoutContentMaximize', full)
|
||||
toggleFullscreen()
|
||||
|
||||
if (full) {
|
||||
enter()
|
||||
} else {
|
||||
exit()
|
||||
}
|
||||
|
||||
if (scrollToOptions && full) {
|
||||
LAYOUT_CONTENT_REF?.value?.scrollTo(scrollToOptions)
|
||||
contentEl?.value?.scrollTo(scrollToOptions)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isLayoutContentMaximized,
|
||||
isFullscreen,
|
||||
maximize,
|
||||
toggleFullscreen,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,8 @@ export type CloseMenuTag = Key | MenuTagOptions
|
||||
* @param target 标签页对象、索引、key
|
||||
* @param fn 触发函数
|
||||
*
|
||||
* 该方法用于统一获取目标标签页方法
|
||||
* @description
|
||||
* 该方法用于统一获取目标标签页方法。
|
||||
*/
|
||||
const normalMenuTagOption = (target: CloseMenuTag, fn: string) => {
|
||||
const { getMenuTagOptions } = useMenuGetters()
|
||||
@ -82,27 +83,14 @@ export function useSiderBar() {
|
||||
resolveOption,
|
||||
} = useMenuActions()
|
||||
|
||||
/**
|
||||
*
|
||||
* @remark 获取当前激活标签页索引位置
|
||||
*/
|
||||
// 获取当前激活标签页索引位置
|
||||
const getCurrentTagIndex = () => {
|
||||
return getMenuTagOptions.value.findIndex(
|
||||
(curr) => curr.fullPath === getMenuKey.value,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 当前关闭项
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*
|
||||
* @remark 校验指定标签右侧是否有可关闭的标签
|
||||
*/
|
||||
// 校验指定标签右侧是否有可关闭的标签
|
||||
const checkCloseRight = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'checkCloseRight')
|
||||
|
||||
@ -116,17 +104,7 @@ export function useSiderBar() {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 当前关闭项
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*
|
||||
* @remark 校验指定标签左侧是否有可关闭的标签
|
||||
*/
|
||||
// 校验指定标签左侧是否有可关闭的标签
|
||||
const checkCloseLeft = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'checkCloseRight')
|
||||
|
||||
@ -148,15 +126,7 @@ export function useSiderBar() {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 当前关闭项
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*/
|
||||
// 关闭当前标签
|
||||
const close = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'close')
|
||||
|
||||
@ -187,10 +157,7 @@ export function useSiderBar() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 关闭所有标签并且导航至 root path
|
||||
*/
|
||||
// 关闭所有标签并且导航至 root path
|
||||
const closeAll = () => {
|
||||
spliceMenTagOptions(0, getMenuTagOptions.value.length)
|
||||
|
||||
@ -217,18 +184,7 @@ export function useSiderBar() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 目标标签页
|
||||
*
|
||||
* 关闭以当前项为索引的右侧标签
|
||||
* 如果当前选择标签与 menuKey 不匹配并且包含了当前激活标签页,则会关闭当前标签右侧所有变迁并且跳转至该页面
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*/
|
||||
// 目标标签页右侧所有标签页
|
||||
const closeRight = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'closeRight')
|
||||
|
||||
@ -247,18 +203,7 @@ export function useSiderBar() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 目标标签页
|
||||
*
|
||||
* 关闭以当前项左侧所有标签
|
||||
* 如果当前选择标签与 menuKey 不匹配并且包含了当前激活标签页,则会关闭当前标签左侧所有变迁并且跳转至该页面
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*/
|
||||
// 关闭目标标签页左侧所有标签页
|
||||
const closeLeft = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'closeLeft')
|
||||
|
||||
@ -276,17 +221,7 @@ export function useSiderBar() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target 目标标签页
|
||||
*
|
||||
* 会关闭除了当前索引的所有菜单项
|
||||
*
|
||||
* 传递参数类型情况:
|
||||
* - number: 关闭当前项索引
|
||||
* - string: 关闭当前项 key,其实 key 也是一个具体的页面 url 地址
|
||||
* - AppMenuOption: 关闭当前项
|
||||
*/
|
||||
// 关闭除了当前索引的所有菜单项
|
||||
const closeOther = (target: CloseMenuTag) => {
|
||||
const normal = normalMenuTagOption(target, 'closeOther')
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { unrefElement, effectDispose, isValueType, setStyle } from '@/utils'
|
||||
import { unrefElement, effectDispose, isValueType } from '@/utils'
|
||||
import { pick } from 'lodash-es'
|
||||
|
||||
import type { BasicTarget } from '@/types'
|
||||
|
||||
@ -61,10 +62,9 @@ export interface UseElementFullscreenOptions {
|
||||
transition?: string
|
||||
}
|
||||
|
||||
let currentZIndex = 999
|
||||
let isAppend = false
|
||||
const ID_TAG = 'ELEMENT-FULLSCREEN-RAY'
|
||||
const styleElement = document.createElement('style')
|
||||
// 全局 z-index 管理
|
||||
let globalZIndex = 999
|
||||
const ID_TAG = 'data-element-fullscreen'
|
||||
|
||||
/**
|
||||
*
|
||||
@ -101,141 +101,163 @@ export const useElementFullscreen = (
|
||||
exit: _exit,
|
||||
backgroundColor,
|
||||
zIndex,
|
||||
transition = 'transform 0.3s var(--r-bezier)',
|
||||
transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
} = options ?? {}
|
||||
let isSetup = false
|
||||
const catchBoundingClientRect: {
|
||||
x: number | null
|
||||
y: number | null
|
||||
} = {
|
||||
x: null,
|
||||
y: null,
|
||||
}
|
||||
// 使用 ref 来追踪状态
|
||||
const isFullscreen = ref(false)
|
||||
|
||||
const updateStyle = () => {
|
||||
// 每个实例独立的状态
|
||||
const isFullscreen = ref(false)
|
||||
const instanceZIndex = ref(0)
|
||||
const originalStyles = {
|
||||
position: '',
|
||||
width: '',
|
||||
height: '',
|
||||
top: '',
|
||||
left: '',
|
||||
transform: '',
|
||||
transition: '',
|
||||
zIndex: '',
|
||||
backgroundColor: '',
|
||||
}
|
||||
|
||||
const enter = () => {
|
||||
const element = unrefElement(target) as HTMLElement | null
|
||||
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
const { left, top } = element.getBoundingClientRect()
|
||||
|
||||
if (
|
||||
catchBoundingClientRect.x === null &&
|
||||
catchBoundingClientRect.y === null
|
||||
) {
|
||||
catchBoundingClientRect.x = -left
|
||||
catchBoundingClientRect.y = -top
|
||||
}
|
||||
|
||||
setStyle(document.body, {
|
||||
'--element-fullscreen-z-index':
|
||||
isValueType<null>(zIndex, 'Null') ||
|
||||
isValueType<undefined>(zIndex, 'Undefined')
|
||||
? currentZIndex
|
||||
: zIndex,
|
||||
'--element-fullscreen-transition': transition,
|
||||
'--element-fullscreen-background-color': backgroundColor,
|
||||
'--element-fullscreen-width': 'var(--html-width)',
|
||||
'--element-fullscreen-height': 'var(--html-height)',
|
||||
'--element-fullscreen-transform-x': `${catchBoundingClientRect.x}px`,
|
||||
'--element-fullscreen-transform-y': `${catchBoundingClientRect.y}px`,
|
||||
})
|
||||
|
||||
const cssContent = `
|
||||
[${ID_TAG}] {
|
||||
position: fixed;
|
||||
width: var(--element-fullscreen-width) !important;
|
||||
height: var(--element-fullscreen-height) !important;
|
||||
transform: translate(var(--element-fullscreen-transform-x), var(--element-fullscreen-transform-y)) !important;
|
||||
transition: var(--element-fullscreen-transition);
|
||||
z-index: var(--element-fullscreen-z-index) !important;
|
||||
background-color: var(--element-fullscreen-background-color);
|
||||
}
|
||||
`.trim()
|
||||
|
||||
styleElement.innerHTML = cssContent
|
||||
|
||||
// 避免重复添加 style 标签
|
||||
if (!isAppend) {
|
||||
document.head.appendChild(styleElement)
|
||||
}
|
||||
}
|
||||
|
||||
const enter = () => {
|
||||
const element = unrefElement(target) as HTMLElement | null
|
||||
|
||||
beforeEnter?.()
|
||||
|
||||
if (element) {
|
||||
if (!element.getAttribute(ID_TAG)) {
|
||||
element.setAttribute(ID_TAG, ID_TAG)
|
||||
}
|
||||
// 保存原始样式(只在第一次进入时保存)
|
||||
if (!isFullscreen.value) {
|
||||
const o = pick(element.style, [
|
||||
'position',
|
||||
'width',
|
||||
'height',
|
||||
'top',
|
||||
'left',
|
||||
'transform',
|
||||
'transition',
|
||||
'zIndex',
|
||||
'backgroundColor',
|
||||
])
|
||||
|
||||
if (!isSetup) {
|
||||
isSetup = true
|
||||
currentZIndex += 1
|
||||
}
|
||||
|
||||
if (!isAppend) {
|
||||
updateStyle()
|
||||
|
||||
isAppend = true
|
||||
}
|
||||
|
||||
element.style.transition = transition
|
||||
isFullscreen.value = true
|
||||
|
||||
_enter?.()
|
||||
Object.assign(originalStyles, o)
|
||||
}
|
||||
|
||||
// 获取当前位置
|
||||
const { top, left, width, height } = element.getBoundingClientRect()
|
||||
|
||||
// 分配 z-index
|
||||
if (instanceZIndex.value === 0) {
|
||||
if (
|
||||
isValueType<null>(zIndex, 'Null') ||
|
||||
isValueType<undefined>(zIndex, 'Undefined')
|
||||
) {
|
||||
globalZIndex += 1
|
||||
instanceZIndex.value = globalZIndex
|
||||
} else {
|
||||
instanceZIndex.value = zIndex
|
||||
}
|
||||
}
|
||||
|
||||
// 设置全屏样式
|
||||
element.setAttribute(ID_TAG, 'true')
|
||||
|
||||
// 设置初始位置(不设置 transition)
|
||||
element.style.position = 'fixed'
|
||||
element.style.top = `${top}px`
|
||||
element.style.left = `${left}px`
|
||||
element.style.width = `${width}px`
|
||||
element.style.height = `${height}px`
|
||||
element.style.transform = 'translate(0, 0)'
|
||||
element.style.zIndex = String(instanceZIndex.value)
|
||||
|
||||
if (backgroundColor) {
|
||||
element.style.backgroundColor = backgroundColor
|
||||
}
|
||||
|
||||
// 强制重排
|
||||
void element.offsetHeight
|
||||
|
||||
// 添加 transition
|
||||
element.style.transition = transition
|
||||
|
||||
// 使用 requestAnimationFrame 应用最终样式
|
||||
requestAnimationFrame(() => {
|
||||
element.style.top = '0px'
|
||||
element.style.left = '0px'
|
||||
element.style.width = '100vw'
|
||||
element.style.height = '100vh'
|
||||
})
|
||||
|
||||
// 先更新状态
|
||||
isFullscreen.value = true
|
||||
|
||||
_enter?.()
|
||||
}
|
||||
|
||||
const exit = () => {
|
||||
beforeExit?.()
|
||||
const element = unrefElement(target) as HTMLElement | null
|
||||
|
||||
const element = unrefElement(target)
|
||||
|
||||
if (element) {
|
||||
element.removeAttribute(ID_TAG)
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
beforeExit?.()
|
||||
|
||||
// 先更新状态
|
||||
isFullscreen.value = false
|
||||
|
||||
// 恢复原始样式
|
||||
element.removeAttribute(ID_TAG)
|
||||
|
||||
// 样式属性映射表(camelCase -> kebab-case)
|
||||
const styleMap: Record<keyof typeof originalStyles, string> = {
|
||||
position: 'position',
|
||||
width: 'width',
|
||||
height: 'height',
|
||||
top: 'top',
|
||||
left: 'left',
|
||||
transform: 'transform',
|
||||
transition: 'transition',
|
||||
zIndex: 'z-index',
|
||||
backgroundColor: 'background-color',
|
||||
}
|
||||
|
||||
// 批量恢复样式
|
||||
Object.entries(originalStyles).forEach(([key, value]) => {
|
||||
const styleName = styleMap[key as keyof typeof originalStyles]
|
||||
|
||||
if (!value) {
|
||||
element.style.removeProperty(styleName)
|
||||
} else {
|
||||
element.style.setProperty(styleName, value)
|
||||
}
|
||||
})
|
||||
|
||||
_exit?.()
|
||||
}
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
const element = unrefElement(target)
|
||||
|
||||
if (element) {
|
||||
if (element.getAttribute(ID_TAG)) {
|
||||
exit()
|
||||
} else {
|
||||
enter()
|
||||
}
|
||||
if (isFullscreen.value) {
|
||||
exit()
|
||||
} else {
|
||||
enter()
|
||||
}
|
||||
}
|
||||
|
||||
effectDispose(() => {
|
||||
const element = unrefElement(target) as HTMLElement | null
|
||||
|
||||
if (element) {
|
||||
element.removeAttribute(ID_TAG)
|
||||
if (isFullscreen.value) {
|
||||
exit()
|
||||
}
|
||||
|
||||
// 回滚 z-index 值,避免无限增加
|
||||
currentZIndex = Math.max(999, currentZIndex - 1) // 防止 zIndex 小于初始值
|
||||
isFullscreen.value = false
|
||||
})
|
||||
|
||||
return {
|
||||
enter,
|
||||
exit,
|
||||
toggleFullscreen,
|
||||
isFullscreen: readonly(isFullscreen), // 暴露只读状态
|
||||
isFullscreen: readonly(isFullscreen),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,26 +48,19 @@ const DEFAULT_OPTIONS: UsePaginationOptions = {
|
||||
* @param options 配置项
|
||||
*
|
||||
* @description
|
||||
* 便捷分页 hook。
|
||||
* Naive UI Pagination 便捷分页 hook。
|
||||
*
|
||||
* @example
|
||||
* const [paginationRef, { getItemCount, setItemCount, getPage, setPage, getPageSize, setPageSize, getPagination, getCallback, setCallback, resetPagination }] = usePagination(() => {
|
||||
* // do something...
|
||||
* }, {
|
||||
* // ...options
|
||||
* })
|
||||
*/
|
||||
export const usePagination = <T extends AnyFC>(
|
||||
callback?: T,
|
||||
options?: UsePaginationOptions,
|
||||
) => {
|
||||
// 配置合并
|
||||
const mergedOptions = computed(() => ({
|
||||
...DEFAULT_OPTIONS,
|
||||
...omit(options, [
|
||||
'on-update:page',
|
||||
'on-update:page-size',
|
||||
'onUpdatePage',
|
||||
'onUpdatePageSize',
|
||||
'onUpdate:page',
|
||||
'onUpdate:page-size',
|
||||
'onUpdate:pageSize',
|
||||
]),
|
||||
...paginationMethods,
|
||||
}))
|
||||
// 回调函数
|
||||
const callbackRef = shallowRef(callback)
|
||||
// 分页方法
|
||||
@ -90,6 +83,20 @@ export const usePagination = <T extends AnyFC>(
|
||||
pageSizeChange?.(pageSize)
|
||||
},
|
||||
}
|
||||
// 配置合并
|
||||
const mergedOptions = computed(() => ({
|
||||
...DEFAULT_OPTIONS,
|
||||
...omit(options, [
|
||||
'on-update:page',
|
||||
'on-update:page-size',
|
||||
'onUpdatePage',
|
||||
'onUpdatePageSize',
|
||||
'onUpdate:page',
|
||||
'onUpdate:page-size',
|
||||
'onUpdate:pageSize',
|
||||
]),
|
||||
...paginationMethods,
|
||||
}))
|
||||
// 分页配置
|
||||
const paginationRef = ref<PaginationProps>(mergedOptions.value)
|
||||
|
||||
@ -171,7 +178,12 @@ export const usePagination = <T extends AnyFC>(
|
||||
* @description
|
||||
* 获取回调函数。
|
||||
*/
|
||||
const getCallback = callbackRef.value as T
|
||||
const getCallback = <Fn extends AnyFC = T>(): Fn extends
|
||||
| undefined
|
||||
| null
|
||||
| unknown
|
||||
? T
|
||||
: Fn => callbackRef.value
|
||||
|
||||
/**
|
||||
*
|
||||
@ -183,7 +195,7 @@ export const usePagination = <T extends AnyFC>(
|
||||
* @example
|
||||
* setCallback(() => {})
|
||||
*/
|
||||
const setCallback = (callback: AnyFC) => {
|
||||
const setCallback = <Fn extends AnyFC = AnyFC>(callback: Fn) => {
|
||||
callbackRef.value = callback
|
||||
}
|
||||
|
||||
|
||||
@ -13,10 +13,6 @@ $menuTagWrapperWidth: 76px;
|
||||
& .menu-tag-wrapper {
|
||||
width: calc(100% - $space * 2 - $menuTagWrapperWidth);
|
||||
}
|
||||
|
||||
& .ray-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
& .n-tag {
|
||||
@ -51,15 +47,14 @@ $menuTagWrapperWidth: 76px;
|
||||
}
|
||||
}
|
||||
|
||||
.ray-template--light {
|
||||
.menu-tag__btn-icon:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
.ray-template--light,
|
||||
.ray-template--dark {
|
||||
.menu-tag__btn-icon:hover {
|
||||
filter: brightness(0.8);
|
||||
.menu-tag__btn .menu-tag__btn-icon {
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--n-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,14 +21,7 @@
|
||||
|
||||
import './index.scss'
|
||||
|
||||
import {
|
||||
NScrollbar,
|
||||
NFlex,
|
||||
NLayoutHeader,
|
||||
NDropdown,
|
||||
NButton,
|
||||
NIcon,
|
||||
} from 'naive-ui'
|
||||
import { NScrollbar, NFlex, NLayoutHeader, NDropdown, NButton } from 'naive-ui'
|
||||
import { RIcon, RMoreDropdown } from '@/components'
|
||||
|
||||
import { useMenuGetters, useMenuActions } from '@/store'
|
||||
@ -451,7 +444,7 @@ export default defineComponent({
|
||||
show={this.actionState.actionDropdownShow}
|
||||
trigger="manual"
|
||||
placement="bottom-start"
|
||||
onSelect={actionDropdownSelect.bind(this)}
|
||||
onSelect={actionDropdownSelect}
|
||||
onClickoutside={() => {
|
||||
if (!isMouseInMenuTag) {
|
||||
this.actionState.actionDropdownShow = false
|
||||
@ -544,6 +537,7 @@ export default defineComponent({
|
||||
{...{
|
||||
onMousedown: closeCurrentMenuTag.bind(this, idx),
|
||||
}}
|
||||
cursor="pointer"
|
||||
/>
|
||||
),
|
||||
}}
|
||||
|
||||
@ -14,8 +14,8 @@ $globalSearchWidth: 650px;
|
||||
border-radius: 6px;
|
||||
min-width: 560px;
|
||||
|
||||
& .ray-icon {
|
||||
color: var(--ray-theme-primary-color);
|
||||
& .r-icon {
|
||||
color: var(--r-theme-primary-color);
|
||||
}
|
||||
|
||||
& .n-card__action {
|
||||
@ -59,7 +59,7 @@ $globalSearchWidth: 650px;
|
||||
.n-flex.global-search__card-content {
|
||||
& .content-item.content-item--active,
|
||||
& .content-item:hover {
|
||||
background-color: var(--ray-theme-primary-fade-color);
|
||||
background-color: var(--r-theme-primary-fade-color);
|
||||
}
|
||||
|
||||
& .content-item {
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
color 0.3s var(--r-bezier),
|
||||
background-color 0.3s var(--r-bezier);
|
||||
|
||||
& .ray-icon {
|
||||
& .r-icon {
|
||||
transform: translate(-14px, 14px);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
.r-menu--app:not(.n-menu--collapsed)
|
||||
.n-menu-item-content.n-menu-item-content--selected:before,
|
||||
.r-menu--app:not(.n-menu--collapsed) .n-menu-item-content:hover:before {
|
||||
border-left: 4px solid var(--ray-theme-primary-color);
|
||||
border-left: 4px solid var(--r-theme-primary-color);
|
||||
transition: border-left 0.1s;
|
||||
}
|
||||
|
||||
|
||||
@ -39,12 +39,13 @@ export default defineComponent({
|
||||
</NCard>
|
||||
</NGridItem>
|
||||
<NGridItem span={1}>
|
||||
<NCard title="基础条形码">
|
||||
<NCard title="根据尺寸自动更新的条形码">
|
||||
<RBarcode
|
||||
text="RayTemplate"
|
||||
options={{
|
||||
...baseOptions,
|
||||
}}
|
||||
responsive
|
||||
/>
|
||||
</NCard>
|
||||
</NGridItem>
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
NSelect,
|
||||
NDatePicker,
|
||||
NText,
|
||||
useDialog,
|
||||
} from 'naive-ui'
|
||||
import { RIcon } from '@/components'
|
||||
|
||||
@ -98,6 +99,7 @@ export default defineComponent({
|
||||
name: 'TableProDemo',
|
||||
setup() {
|
||||
const { format } = useDayjs()
|
||||
const { info: infoDialog } = useDialog()
|
||||
|
||||
const [register, { formModel, reset }] = useForm<ParamsRef>({
|
||||
RangeTime: null,
|
||||
@ -312,6 +314,7 @@ export default defineComponent({
|
||||
setPage,
|
||||
setPageSize,
|
||||
resetTablePagination,
|
||||
infoDialog,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
@ -338,6 +341,7 @@ export default defineComponent({
|
||||
setPage,
|
||||
setPageSize,
|
||||
resetTablePagination,
|
||||
infoDialog,
|
||||
} = this
|
||||
|
||||
return (
|
||||
@ -428,7 +432,20 @@ export default defineComponent({
|
||||
<NButton type="primary" onClick={() => print()}>
|
||||
打印
|
||||
</NButton>
|
||||
<NButton type="primary" onClick={() => downloadCsv()}>
|
||||
<NButton
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
infoDialog({
|
||||
title: '下载 CSV',
|
||||
content: '下载 CSV',
|
||||
positiveText: '下载',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
downloadCsv()
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
下载 csv
|
||||
</NButton>
|
||||
<NButton type="primary" onClick={() => setPage(2)}>
|
||||
|
||||
@ -203,7 +203,7 @@ export default defineComponent({
|
||||
maximize(!this.maximizeRef, {
|
||||
scrollToOptions: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
top: -9999,
|
||||
},
|
||||
})
|
||||
}}
|
||||
|
||||
1
unplugin/components.d.ts
vendored
1
unplugin/components.d.ts
vendored
@ -10,5 +10,6 @@ declare module 'vue' {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Src: typeof import('./../src/components/base/RTransitionComponent/src/index.vue')['default']
|
||||
TransitionComponent: typeof import('./../src/components/base/RTransitionComponent/src/TransitionComponent.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,12 @@ function baseOptions(mode: string): PluginOption[] {
|
||||
preloadingConfig,
|
||||
appPrimaryColor,
|
||||
}),
|
||||
viteInspect(), // 仅适用于开发模式(检查 `Vite` 插件的中间状态)
|
||||
// 仅适用于开发模式(检查 `Vite` 插件的中间状态)
|
||||
mode === 'development'
|
||||
? viteInspect({
|
||||
enabled: true,
|
||||
})
|
||||
: null,
|
||||
mockDevServerPlugin({
|
||||
include: ['mock/**/*.mock.ts'],
|
||||
exclude: [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user