Merge remote-tracking branch 'vben/main' into Gf-Vben-Admin

# Conflicts:
#	.github/workflows/deploy.yml
#	.github/workflows/ftp-schedule.yml
#	src/views/sys/login/LoginForm.vue
This commit is contained in:
JinMao 2021-08-25 08:54:16 +08:00
commit c188d8398d
257 changed files with 3236 additions and 3035 deletions

View File

@ -25,6 +25,7 @@ module.exports = defineConfig({
'plugin:jest/recommended', 'plugin:jest/recommended',
], ],
rules: { rules: {
'vue/script-setup-uses-vars': 'error',
'@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
@ -61,7 +62,6 @@ module.exports = defineConfig({
'vue/singleline-html-element-content-newline': 'off', 'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off', 'vue/attribute-hyphenation': 'off',
'vue/require-default-prop': 'off', 'vue/require-default-prop': 'off',
'vue/script-setup-uses-vars': 'off',
'vue/html-self-closing': [ 'vue/html-self-closing': [
'error', 'error',
{ {

2
.vscode/launch.json vendored
View File

@ -8,6 +8,6 @@
"url": "http://localhost:3100", "url": "http://localhost:3100",
"webRoot": "${workspaceFolder}/src", "webRoot": "${workspaceFolder}/src",
"sourceMaps": true "sourceMaps": true
}, }
] ]
} }

View File

@ -117,6 +117,7 @@
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
"i18n-ally.enabledParsers": ["ts"], "i18n-ally.enabledParsers": ["ts"],
"i18n-ally.sourceLanguage": "en", "i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue", "react"], "i18n-ally.enabledFrameworks": ["vue", "react"],
"cSpell.words": [ "cSpell.words": [
"vben", "vben",

View File

@ -1,3 +1,27 @@
## 2.7.1(2021-08-16)
- Upgrade vue 3.2, if the operation fails, delete node_modules and reinstall it
### ✨ Features
- **BasicTree** Add search function related properties and methods
- **BasicForm** added `alwaysShowLines` to set the number of lines kept displayed when folding
### 🐛 Bug Fixes
- **Cropper** Fix the problem of failure to destroy in time
- **BasicTable**
- Fix the problem that `CellFormat` cannot use `Map` type data
- Fixed an issue where the editable cell failed to display the `0` value correctly
- Fixed the issue that selection-change event failed to trigger correctly when unchecked
- Fix the problem that the background color of the full screen state under the light theme is incorrect
- Fix the problem of obtaining complete data when `getSelectRows` does not support remote data cross-page selection
- Fix the issue that the `size` property provided for editing components in `editComponentProps` is invalid
- **Qrcode** Fixed the problem that the QR code component could not be drawn in time when it was created
- **BasicModal** Fix the problem that the `helpMessage` property does not work
- **BasicButton** Fix the problem that the button style performance is inconsistent with the official antd
- **Others** Fix the problem that `useRedo` (reload the current route) will lose route `params` data
## 2.7.0(2021-08-03) ## 2.7.0(2021-08-03)
## (Breaking changes) Breaking changes ## (Breaking changes) Breaking changes

View File

@ -1,3 +1,90 @@
## [2.7.1](https://github.com/anncwb/vue-vben-admin/compare/v2.6.1...v2.7.1) (2021-08-16)
### Bug Fixes
- `slots` working in components ([b1f3176](https://github.com/anncwb/vue-vben-admin/commit/b1f31762e3c86a432a8d559ab957444eaf5525ad))
- add axios error info from response ([#1083](https://github.com/anncwb/vue-vben-admin/issues/1083)) ([72634ff](https://github.com/anncwb/vue-vben-admin/commit/72634ffe6e6649d36ee41f7633c8ee2ab80cf25e))
- auto remove script dom in `useScript` ([a544dd3](https://github.com/anncwb/vue-vben-admin/commit/a544dd3e589329339177dad3d5c1f75dd6e6f0ca))
- fixed `useRedo` may loss route params ([2dd3d85](https://github.com/anncwb/vue-vben-admin/commit/2dd3d8544866231895d23dba63785b683ae0062e)), closes [#1079](https://github.com/anncwb/vue-vben-admin/issues/1079)
- fixed basicButton ghost style ([3ba8a67](https://github.com/anncwb/vue-vben-admin/commit/3ba8a67647d35fb9639a5af66f33d43eff493d15))
- fixed basicButton primary style ([1b57792](https://github.com/anncwb/vue-vben-admin/commit/1b577922e752c02fe7c033c53be37ef81e4e9b8e))
- fixed basicButton style ([beb4ae9](https://github.com/anncwb/vue-vben-admin/commit/beb4ae92c190780bbd3bc6bc7547d52e2ccf8cf1))
- **cropper:** cropper not destroy in time ([3819430](https://github.com/anncwb/vue-vben-admin/commit/381943078fd55123fde3d5555e04f279d7f1c407)), closes [#1027](https://github.com/anncwb/vue-vben-admin/issues/1027)
- **demo:** fix form style in modal ([30c5fc6](https://github.com/anncwb/vue-vben-admin/commit/30c5fc63c8600cfb03f917d79e56c0a7e7ff64e0)), closes [#1076](https://github.com/anncwb/vue-vben-admin/issues/1076)
- **i18n:** add i18n translate data ([1f55c41](https://github.com/anncwb/vue-vben-admin/commit/1f55c4180f9c0cf48e3796a77d6f0bfd46107272))
- **locales:** fix that vscode extension i18n-Ally detect zh-CN as zh ([#1044](https://github.com/anncwb/vue-vben-admin/issues/1044)) ([b2d49cb](https://github.com/anncwb/vue-vben-admin/commit/b2d49cbbf81cb15e75905deb95bdf7ac4af4e599))
- **modal:** `helpMessage` doesn't work ([953bfc6](https://github.com/anncwb/vue-vben-admin/commit/953bfc6f1a559309ea2b1114b8ede911a3751cc7))
- **page-wrapper:** fix `class` not working ([8879ae8](https://github.com/anncwb/vue-vben-admin/commit/8879ae8d773e8dc4c252c4234eefeab9bc135a30))
- **qrcode:** qrcode not displayed properly ([26f251e](https://github.com/anncwb/vue-vben-admin/commit/26f251e1ed5bfd79c8615fb552ca302f917cc588)), closes [#1026](https://github.com/anncwb/vue-vben-admin/issues/1026)
- **route:** the whitelist should include basicRoutes ([#1048](https://github.com/anncwb/vue-vben-admin/issues/1048)) ([1bb5156](https://github.com/anncwb/vue-vben-admin/commit/1bb51569236fd9bcc55dd9f237f51f218956b258))
- **table:** `0` is not shown in editable cell ([33a335a](https://github.com/anncwb/vue-vben-admin/commit/33a335a3f52aead522b3fbee0d558e2e797580ff)), closes [#1039](https://github.com/anncwb/vue-vben-admin/issues/1039)
- **table:** `cellFormat` support `Map` ([1214b7c](https://github.com/anncwb/vue-vben-admin/commit/1214b7c32c425750a4d0202a9b235eb9e45a6f47)), closes [#1031](https://github.com/anncwb/vue-vben-admin/issues/1031)
- **table:** `getSelectRows` support multi-page ([4b6025c](https://github.com/anncwb/vue-vben-admin/commit/4b6025cb9a3ef067680201ec3052bc651e0a0c1b)), closes [#914](https://github.com/anncwb/vue-vben-admin/issues/914)
- **table:** `selection-change` not triggered in unchecking ([019555b](https://github.com/anncwb/vue-vben-admin/commit/019555be0c88edc673cae382023d647e78959b30)), closes [#1053](https://github.com/anncwb/vue-vben-admin/issues/1053)
- **table:** `size` not worked in `editComponentProps` ([7971896](https://github.com/anncwb/vue-vben-admin/commit/7971896383296c155b7ab16b5beb3544f34ee525)), closes [#1074](https://github.com/anncwb/vue-vben-admin/issues/1074)
- **table:** fix `getSelectRows` for treeTable ([f2b8bb4](https://github.com/anncwb/vue-vben-admin/commit/f2b8bb43a0b9172b9ef9ced8e83bf91143a091d9)), closes [#1003](https://github.com/anncwb/vue-vben-admin/issues/1003)
- **table:** fix `injection not found` warning ([53e79a2](https://github.com/anncwb/vue-vben-admin/commit/53e79a2d94df19c0e1aa7399d5ce4c27834e0350))
- **types:** fix some type errors ([9035fd1](https://github.com/anncwb/vue-vben-admin/commit/9035fd191e4e8d954f42b3a4cd1e80ec70b7cbb6))
- The Style of tableTitle slot ([#1023](https://github.com/anncwb/vue-vben-admin/issues/1023)) ([02e7756](https://github.com/anncwb/vue-vben-admin/commit/02e77560624cc4a95a5a20ffd5e0601f1f88c6f4))
- fix build handler & misc ([#1060](https://github.com/anncwb/vue-vben-admin/issues/1060)) ([66feb77](https://github.com/anncwb/vue-vben-admin/commit/66feb779a8645a93760c784c510512118c4c6efa))
- **table:** recursive updateTableDataRecord ([#1024](https://github.com/anncwb/vue-vben-admin/issues/1024)) ([72f953c](https://github.com/anncwb/vue-vben-admin/commit/72f953c8d3413a7f5482793258503017a81cc759))
- **table:** wrong bg-color in fullscreen mode ([2052eb5](https://github.com/anncwb/vue-vben-admin/commit/2052eb5a65be38c44165efecdb15266de4638667))
- **type:** fix ant-design-vue -> ([#1043](https://github.com/anncwb/vue-vben-admin/issues/1043)) ([6d5388a](https://github.com/anncwb/vue-vben-admin/commit/6d5388aaf143ac76bac0b68d56a3ab6b5993e807))
- fix iframe heigth error ([#1012](https://github.com/anncwb/vue-vben-admin/issues/1012)) ([d76cfd7](https://github.com/anncwb/vue-vben-admin/commit/d76cfd7f809ba48880c950a64cb43a5c9c44176c))
- Fix the invalid hot update of BasicButton when changing style outside ([#1016](https://github.com/anncwb/vue-vben-admin/issues/1016)) ([be2d11d](https://github.com/anncwb/vue-vben-admin/commit/be2d11d5d344a508e94abe3534726c80e1f1f271))
- the position of tinymce upload image is wrong ([#1015](https://github.com/anncwb/vue-vben-admin/issues/1015)) ([2fd0fd2](https://github.com/anncwb/vue-vben-admin/commit/2fd0fd281e65d6d2551478c5f19250347dc14062))
- **tree:** fix `checkAll` effects `disabled` node ([ddd1893](https://github.com/anncwb/vue-vben-admin/commit/ddd1893b113e13786037522341abb2e75f8f9d5b))
- style property of actionColOpt is invalid ([#997](https://github.com/anncwb/vue-vben-admin/issues/997)) ([225bd4c](https://github.com/anncwb/vue-vben-admin/commit/225bd4c39de377d93c605f33bfdf3d8fd565f12b))
- typo ([#980](https://github.com/anncwb/vue-vben-admin/issues/980)) ([7e6a89f](https://github.com/anncwb/vue-vben-admin/commit/7e6a89ffeb8c63467908d5807d3d7c4761620ee3))
- **api-tree-select:** auto reload while `params` changed ([c734f68](https://github.com/anncwb/vue-vben-admin/commit/c734f6858daea6d11cd517463b06fcce58744947))
- **dark-theme:** alert color in dark-theme ([9b7ede0](https://github.com/anncwb/vue-vben-admin/commit/9b7ede09b9efe4d5a15ab0cdeadac480a29c0f62))
- **dark-theme:** bgcolor of `selected tree node` in dark theme ([8cf004a](https://github.com/anncwb/vue-vben-admin/commit/8cf004a5f59895e2487c3a350c83000e585b897e)), closes [#949](https://github.com/anncwb/vue-vben-admin/issues/949)
- **dark-theme:** disabled link `button` color ([4281216](https://github.com/anncwb/vue-vben-admin/commit/42812162c46832ce4d3e332bd579c042309115bc))
- **dark-theme:** fixed `TreeSelect` & `DatePicker` theme ([d1e0e8b](https://github.com/anncwb/vue-vben-admin/commit/d1e0e8bcea1c168631222989969e14f7d0d1b6a4)), closes [#955](https://github.com/anncwb/vue-vben-admin/issues/955)
- **dark-theme:** style for checked tree nodes ([662b576](https://github.com/anncwb/vue-vben-admin/commit/662b576ac2088247cb58e295378f228462508a37))
- **demo:** account page form validation ([8702965](https://github.com/anncwb/vue-vben-admin/commit/87029650570e470431fb94d35a273c5d07a73135))
- **demo:** fix roles mock data ([c375e32](https://github.com/anncwb/vue-vben-admin/commit/c375e32305eae5128e09ad1bda39ce0cc6afd790))
- **form:** remove console error for `setFieldsValue` ([8d185bb](https://github.com/anncwb/vue-vben-admin/commit/8d185bb5841c83eb49c78e8342e65067aa6f9b80)), closes [#952](https://github.com/anncwb/vue-vben-admin/issues/952)
- **table:** fix `pagination` props working ([e327893](https://github.com/anncwb/vue-vben-admin/commit/e32789373eb5b1b531572b59692bf552dac365dc))
- expandIcon slot of BasicTable component is invalid ([#975](https://github.com/anncwb/vue-vben-admin/issues/975)) ([98c206d](https://github.com/anncwb/vue-vben-admin/commit/98c206d9c9661a18dde4ec7782cbe1eb6e62ebeb))
- **demo:** menu `error-log` link to 404 page ([341bd63](https://github.com/anncwb/vue-vben-admin/commit/341bd633d8ed38a5a357db8f97166c2eba2895d3))
- **demo:** multi-modal used with dynamic component ([e1c4723](https://github.com/anncwb/vue-vben-admin/commit/e1c47233edf7675aede6d5f023726945a510ddf7))
- **echarts:** fix graphic config cannot be used in echarts options ([#959](https://github.com/anncwb/vue-vben-admin/issues/959)) ([525484e](https://github.com/anncwb/vue-vben-admin/commit/525484e7a409b032d22231f90a92e700ef4290ae))
- **form:** fix `validate` promise catch ([571f281](https://github.com/anncwb/vue-vben-admin/commit/571f28138f782553eb39cda2d632e5ac1aa1e145))
- **img-rotate-drag-verify:** fix `resume` method support ([32d64db](https://github.com/anncwb/vue-vben-admin/commit/32d64dbe816a0afda6ee9e91863199afb3e7b48e)), closes [#946](https://github.com/anncwb/vue-vben-admin/issues/946)
- **login:** fix `auto fill` style in dark-theme ([cebc6a5](https://github.com/anncwb/vue-vben-admin/commit/cebc6a590e1a19af7380a55aed43b23af274df0a))
- **perm-guard:** Fix the problem that the routing query is lost after refreshing the page ([#941](https://github.com/anncwb/vue-vben-admin/issues/941)) ([9c4889f](https://github.com/anncwb/vue-vben-admin/commit/9c4889f0859bc60decf0ef40c383c1946de1d68a))
- **qrcode:** Fix the problem that the QR code cannot be dynamically generated ([#974](https://github.com/anncwb/vue-vben-admin/issues/974)) ([fe4eae3](https://github.com/anncwb/vue-vben-admin/commit/fe4eae37146068f01ba08f033e0c2e8bd03e48b5))
- **style:** fix checkbox-checked css in dark mode ([d3f08e3](https://github.com/anncwb/vue-vben-admin/commit/d3f08e37c5b6e46f33d525e9ef4b4c235d77a192))
- **table:** component shown in `fullscreen` mode ([a07ab6d](https://github.com/anncwb/vue-vben-admin/commit/a07ab6d7aa1060f856649a9bdbec9dfa50b14f26))
- **table:** editable cell display with validation ([202aa42](https://github.com/anncwb/vue-vben-admin/commit/202aa42b8d5a94e84ad386bcf7feab96926c70dd)), closes [#953](https://github.com/anncwb/vue-vben-admin/issues/953)
- **table:** fix `dataPicker` show in `fullscreen` mode ([a5a9b3f](https://github.com/anncwb/vue-vben-admin/commit/a5a9b3fb34c64b6ea9c9ab3d58045f6e5963952b))
- **table:** fix expand style ([14fb21d](https://github.com/anncwb/vue-vben-admin/commit/14fb21d0b7b9ac69c7b3c463de6d709bd5713d14)), closes [#969](https://github.com/anncwb/vue-vben-admin/issues/969)
- **table:** fix tableSettings popup in fullscreen mode ([dce3fb0](https://github.com/anncwb/vue-vben-admin/commit/dce3fb0f20516aaf4817281f5d08109e53a73ecb))
- **table-action:** stopButtonPropagation not working ([9b8f165](https://github.com/anncwb/vue-vben-admin/commit/9b8f165a365758d001e6d86ae7afe4ae3316d485))
- Fix vite profile hot update error reporting ([#968](https://github.com/anncwb/vue-vben-admin/issues/968)) ([956ed2e](https://github.com/anncwb/vue-vben-admin/commit/956ed2e3f770cc9cf822ce80f71b1e7f179792fb))
- **utils:** The date function gets a non-date when the parameter is null ([#954](https://github.com/anncwb/vue-vben-admin/issues/954)) ([350c85a](https://github.com/anncwb/vue-vben-admin/commit/350c85accf5033cc5a21b71bc36d5b7a74eb2573))
- fixed moment locale config ([27207a7](https://github.com/anncwb/vue-vben-admin/commit/27207a78caccb04372e0275c5cee526ec460de0e))
- typo for utils/env ([#1004](https://github.com/anncwb/vue-vben-admin/issues/1004)) ([e8eefd1](https://github.com/anncwb/vue-vben-admin/commit/e8eefd1bca41c181ec6395bf1d087d2018e2b1f1))
- **table:** fix editable cell not support `ellipsis` ([4bb506f](https://github.com/anncwb/vue-vben-admin/commit/4bb506fb1f6ac7d246f8792d29f337ec003ff426)), closes [#944](https://github.com/anncwb/vue-vben-admin/issues/944)
### Features
- add `updatePath` for `useTabs` ([bcfa338](https://github.com/anncwb/vue-vben-admin/commit/bcfa33822736b761757a2673d977f752cb5c4f7c)), closes [#1068](https://github.com/anncwb/vue-vben-admin/issues/1068)
- always refresh userinfo when page reload ([cc46935](https://github.com/anncwb/vue-vben-admin/commit/cc46935a8296dae62ecfc753a956338ba433927e))
- **demo:** add `async-validator` demo ([8b4b767](https://github.com/anncwb/vue-vben-admin/commit/8b4b767f4ca78f7c6f7586d8ba662552c2b7bb51))
- **form:** add `alwaysShowLines` prop ([93f9a19](https://github.com/anncwb/vue-vben-admin/commit/93f9a19aa16a3e9cb95338417c52d9a398e3f70b)), closes [#1051](https://github.com/anncwb/vue-vben-admin/issues/1051)
- **preview:** add more features ([e23bd26](https://github.com/anncwb/vue-vben-admin/commit/e23bd2696da945291a9b652f1af39ad1936f376b))
- **table:** add getRawDataSource() function ([#1029](https://github.com/anncwb/vue-vben-admin/issues/1029)) ([f3cf162](https://github.com/anncwb/vue-vben-admin/commit/f3cf162af1fa5634d4e562fa5239939af6f26093))
- **tree:** add searchable function ([60577d6](https://github.com/anncwb/vue-vben-admin/commit/60577d6720fd3f8d4d1a88b20ab902d6161a0eec)), closes [#1057](https://github.com/anncwb/vue-vben-admin/issues/1057)
- **use-loading:** add `setTip` method ([26d9476](https://github.com/anncwb/vue-vben-admin/commit/26d9476caff41cc355190604af42e0bd2ef0a353))
- Added support for tailwindcss night mode mechanism ([#998](https://github.com/anncwb/vue-vben-admin/issues/998)) ([189bc6f](https://github.com/anncwb/vue-vben-admin/commit/189bc6feb3f2860be8c531dd1ca996f3a2cff018))
### Performance Improvements
- **table:** fixed code style ([da12da9](https://github.com/anncwb/vue-vben-admin/commit/da12da9d8caeba0e7732551cfbad9b0da3baaac4)), closes [#1070](https://github.com/anncwb/vue-vben-admin/issues/1070)
- improve legacy compatibility ([e2664f6](https://github.com/anncwb/vue-vben-admin/commit/e2664f60029f03642f8b1a6afa9b1998705fce37))
# [2.7.0](https://github.com/anncwb/vue-vben-admin/compare/v2.5.9...v2.7.0) (2021-08-03) # [2.7.0](https://github.com/anncwb/vue-vben-admin/compare/v2.5.9...v2.7.0) (2021-08-03)
### Bug Fixes ### Bug Fixes

View File

@ -1,8 +1,45 @@
### ✨ Features
- **BasicForm** 表单组件新增`Divider`,用于较长表单的区域分割
- **BasicTable** 单元格编辑新增提交回调,将根据回调函数返回的结果来决定是否将数据提交到表格
### 🐛 Bug Fixes
- **CodeEditor** 修复 JSON 编辑器在格式化无效 JSON 文本时会抛出异常的问题
- **Tinymce** 修复 inline 模式在一些场景下会出现异常的问题
- **BasicTable**
- 修复可编辑单元格的内容为空时,不会显示编辑图标的问题
- 修复表尾合计行与表格主体部分的列有时候未能对齐的问题
- **其它**
- 修复部分封装组件在使用插槽时报错的问题
- 修复`useECharts`的`theme`参数不起作用的问题
- 修复`Token`失效时,按 F5 刷新页面可能会出现页面加载异常的问题
- 修复`useRedo`的不当调用可能会导致重定向`path`异常的问题
- 修复`vite`自定义模式名称不支持下划线的问题
## 2.7.1(2021-08-16)
- 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可
### ✨ Features
- **BasicTree** 添加搜索功能相关属性和方法
- **BasicForm** 新增`alwaysShowLines`用于设置折叠时保留显示的行数
### 🐛 Bug Fixes ### 🐛 Bug Fixes
- **Cropper** 修复未能及时销毁的问题 - **Cropper** 修复未能及时销毁的问题
- **BasicTable** 修复`CellFormat`无法使用`Map`类型数据的问题 - **BasicTable**
- 修复`CellFormat`无法使用`Map`类型数据的问题
- 修复可编辑单元格未能正确显示`0`值的问题
- 修复 selection-change 事件在取消勾选时未能正确触发的问题
- 修复浅色主题下的全屏状态背景颜色不正确的问题
- 修复`getSelectRows`不支持远程数据跨页选择时获取完整数据的问题
- 修复在`editComponentProps`中为编辑组件提供的`size`属性无效的问题
- **Qrcode** 修复二维码组件在创建时未能及时绘制的问题 - **Qrcode** 修复二维码组件在创建时未能及时绘制的问题
- **BasicModal** 修复`helpMessage`属性不起作用的问题
- **BasicButton** 修复按钮样式表现与 antd 官方不一致的问题
- **其它** 修复`useRedo`(重新加载当前路由)会丢失路由`params`数据的问题
## 2.7.0(2021-08-03) ## 2.7.0(2021-08-03)

View File

@ -150,6 +150,7 @@ yarn build
## 后台整合示例 ## 后台整合示例
- [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台 - [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台
- [matecloud](https://github.com/matevip/matecloud) - MateCloud 微服务脚手架,基于 Spring Cloud 2020.0.3、SpringBoot 2.5.3 的全开源平台
## 维护者 ## 维护者

View File

@ -28,7 +28,7 @@ export function generateModifyVars(dark = false) {
'success-color': '#55D187', // Success color 'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color 'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color 'warning-color': '#EFBD47', // Warning color
'border-color-base': '#EEEEEE', //'border-color-base': '#EEEEEE',
'font-size-base': '14px', // Main font size 'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet 'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color 'link-color': primary, // Link color

View File

@ -52,19 +52,19 @@ async function generateIcon() {
const { prefix } = data; const { prefix } = data;
const isLocal = useType === 'local'; const isLocal = useType === 'local';
const icons = Object.keys(data.icons).map( const icons = Object.keys(data.icons).map(
(item) => `${isLocal ? prefix + ':' : ''}${item}` (item) => `${isLocal ? prefix + ':' : ''}${item}`,
); );
await fs.writeFileSync( await fs.writeFileSync(
path.join(output, `icons.data.ts`), path.join(output, `icons.data.ts`),
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}` `export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
); );
prefixSet.push(prefix); prefixSet.push(prefix);
} }
} }
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite')); fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
console.log( console.log(
`${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]` `${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
); );
}); });
} }

View File

@ -15,7 +15,7 @@ function createConfig(
configName, configName,
config, config,
configFileName = GLOB_CONFIG_FILE_NAME, configFileName = GLOB_CONFIG_FILE_NAME,
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} } }: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} },
) { ) {
try { try {
const windowConf = `window.${configName}`; const windowConf = `window.${configName}`;

View File

@ -11,7 +11,7 @@ export const runBuild = async () => {
// Generate configuration file // Generate configuration file
if (!argvList.includes('disabled-config')) { if (!argvList.includes('disabled-config')) {
await runBuildConfig(); runBuildConfig();
} }
console.log(`${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!'); console.log(`${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!');

View File

@ -31,7 +31,9 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
if (envName === 'VITE_PROXY') { if (envName === 'VITE_PROXY') {
try { try {
realName = JSON.parse(realName); realName = JSON.parse(realName);
} catch (error) {} } catch (error) {
realName = '';
}
} }
ret[envName] = realName; ret[envName] = realName;
if (typeof realName === 'string') { if (typeof realName === 'string') {
@ -48,7 +50,7 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
*/ */
function getConfFiles() { function getConfFiles() {
const script = process.env.npm_lifecycle_script; const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z]+)'); const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script as string) as any; const result = reg.exec(script as string) as any;
if (result) { if (result) {
const mode = result[1] as string; const mode = result[1] as string;

View File

@ -3,12 +3,11 @@
* https://github.com/anncwb/vite-plugin-compression * https://github.com/anncwb/vite-plugin-compression
*/ */
import type { Plugin } from 'vite'; import type { Plugin } from 'vite';
import compressPlugin from 'vite-plugin-compression'; import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin( export function configCompressPlugin(
compress: 'gzip' | 'brotli' | 'none', compress: 'gzip' | 'brotli' | 'none',
deleteOriginFile = false deleteOriginFile = false,
): Plugin | Plugin[] { ): Plugin | Plugin[] {
const compressList = compress.split(','); const compressList = compress.split(',');
@ -19,16 +18,17 @@ export function configCompressPlugin(
compressPlugin({ compressPlugin({
ext: '.gz', ext: '.gz',
deleteOriginFile, deleteOriginFile,
}) }),
); );
} }
if (compressList.includes('brotli')) { if (compressList.includes('brotli')) {
plugins.push( plugins.push(
compressPlugin({ compressPlugin({
ext: '.br', ext: '.br',
algorithm: 'brotliCompress', algorithm: 'brotliCompress',
deleteOriginFile, deleteOriginFile,
}) }),
); );
} }
return plugins; return plugins;

View File

@ -3,9 +3,7 @@
* https://github.com/anncwb/vite-plugin-html * https://github.com/anncwb/vite-plugin-html
*/ */
import type { Plugin } from 'vite'; import type { Plugin } from 'vite';
import html from 'vite-plugin-html'; import html from 'vite-plugin-html';
import pkg from '../../../package.json'; import pkg from '../../../package.json';
import { GLOB_CONFIG_FILE_NAME } from '../../constant'; import { GLOB_CONFIG_FILE_NAME } from '../../constant';
@ -22,7 +20,7 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
minify: isBuild, minify: isBuild,
inject: { inject: {
// Inject data into ejs template // Inject data into ejs template
injectData: { data: {
title: VITE_GLOB_APP_TITLE, title: VITE_GLOB_APP_TITLE,
}, },
// Embed the generated app.config.js file // Embed the generated app.config.js file

View File

@ -1,6 +1,5 @@
// Image resource files used to compress the output of the production environment // Image resource files used to compress the output of the production environment
// https://github.com/anncwb/vite-plugin-imagemin // https://github.com/anncwb/vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin'; import viteImagemin from 'vite-plugin-imagemin';
export function configImageminPlugin() { export function configImageminPlugin() {

View File

@ -1,9 +1,7 @@
import type { Plugin } from 'vite'; import type { Plugin } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy'; import legacy from '@vitejs/plugin-legacy';
import purgeIcons from 'vite-plugin-purge-icons'; import purgeIcons from 'vite-plugin-purge-icons';
import windiCSS from 'vite-plugin-windicss'; import windiCSS from 'vite-plugin-windicss';
import { configHtmlPlugin } from './html'; import { configHtmlPlugin } from './html';
@ -70,7 +68,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// rollup-plugin-gzip // rollup-plugin-gzip
vitePlugins.push( vitePlugins.push(
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE) configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE),
); );
// vite-plugin-pwa // vite-plugin-pwa

View File

@ -2,7 +2,6 @@
* Zero-config PWA for Vite * Zero-config PWA for Vite
* https://github.com/antfu/vite-plugin-pwa * https://github.com/antfu/vite-plugin-pwa
*/ */
import { VitePWA } from 'vite-plugin-pwa'; import { VitePWA } from 'vite-plugin-pwa';
export function configPwaConfig(env: ViteEnv) { export function configPwaConfig(env: ViteEnv) {

View File

@ -2,11 +2,12 @@
* Introduces component library styles on demand. * Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import * https://github.com/anncwb/vite-plugin-style-import
*/ */
import styleImport from 'vite-plugin-style-import'; import styleImport from 'vite-plugin-style-import';
export function configStyleImportPlugin(isBuild: boolean) { export function configStyleImportPlugin(isBuild: boolean) {
if (!isBuild) return []; if (!isBuild) {
return [];
}
const styleImportPlugin = styleImport({ const styleImportPlugin = styleImport({
libs: [ libs: [
{ {

View File

@ -35,6 +35,11 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
return s; return s;
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)': case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
return s; return s;
default:
if (s.indexOf('.ant-btn') >= -1) {
// 按钮被重新定制过需要过滤掉class防止覆盖
return s;
}
} }
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`; return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
}, },

View File

@ -13,7 +13,7 @@ export function resultPageSuccess<T = any>(
page: number, page: number,
pageSize: number, pageSize: number,
list: T[], list: T[],
{ message = 'ok' } = {} { message = 'ok' } = {},
) { ) {
const pageData = pagination(page, pageSize, list); const pageData = pagination(page, pageSize, list);

View File

@ -52,7 +52,7 @@ export default [
response: ({ body }) => { response: ({ body }) => {
const { username, password } = body; const { username, password } = body;
const checkUser = createFakeUserList().find( const checkUser = createFakeUserList().find(
(item) => item.username === username && password === item.password (item) => item.username === username && password === item.password,
); );
if (!checkUser) { if (!checkUser) {
return resultError('Incorrect account or password'); return resultError('Incorrect account or password');

View File

@ -1,6 +1,6 @@
{ {
"name": "vben-admin", "name": "vben-admin",
"version": "2.7.0", "version": "2.7.1",
"author": { "author": {
"name": "vben", "name": "vben",
"email": "anncwb@126.com", "email": "anncwb@126.com",
@ -34,14 +34,14 @@
"gen:icon": "esno ./build/generate/icon/index.ts" "gen:icon": "esno ./build/generate/icon/index.ts"
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^2.0.3", "@iconify/iconify": "^2.0.4",
"@logicflow/core": "^0.6.6", "@logicflow/core": "^0.6.15",
"@logicflow/extension": "^0.6.6", "@logicflow/extension": "^0.6.15",
"@vueuse/core": "^5.2.0", "@vueuse/core": "^6.0.0",
"@zxcvbn-ts/core": "^1.0.0-beta.0", "@zxcvbn-ts/core": "^1.0.0-beta.0",
"ant-design-vue": "2.2.2", "ant-design-vue": "2.2.6",
"axios": "^0.21.1", "axios": "^0.21.1",
"codemirror": "^5.62.2", "codemirror": "^5.62.3",
"cropperjs": "^1.5.12", "cropperjs": "^1.5.12",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"echarts": "^5.1.2", "echarts": "^5.1.2",
@ -50,46 +50,46 @@
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-to-regexp": "^6.2.0", "path-to-regexp": "^6.2.0",
"pinia": "2.0.0-beta.5", "pinia": "2.0.0-rc.6",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"sortablejs": "^1.14.0", "sortablejs": "^1.14.0",
"tinymce": "^5.8.2", "tinymce": "^5.8.2",
"vditor": "^3.8.6", "vditor": "^3.8.6",
"vue": "3.1.5", "vue": "3.2.4",
"vue-i18n": "9.1.7", "vue-i18n": "9.1.7",
"vue-json-pretty": "^2.0.2", "vue-router": "^4.0.11",
"vue-router": "^4.0.10", "vue-types": "^4.0.3",
"vue-types": "^4.0.1", "xlsx": "^0.17.1",
"xlsx": "^0.17.0" "vue-json-pretty": "1.8.1"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^13.1.0", "@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^13.1.0", "@commitlint/config-conventional": "^13.1.0",
"@iconify/json": "^1.1.382", "@iconify/json": "^1.1.392",
"@purge-icons/generated": "^0.7.0", "@purge-icons/generated": "^0.7.0",
"@types/codemirror": "^5.60.2", "@types/codemirror": "^5.60.2",
"@types/crypto-js": "^4.0.2", "@types/crypto-js": "^4.0.2",
"@types/fs-extra": "^9.0.12", "@types/fs-extra": "^9.0.12",
"@types/inquirer": "^7.3.3", "@types/inquirer": "^7.3.3",
"@types/intro.js": "^3.0.2", "@types/intro.js": "^3.0.2",
"@types/jest": "^26.0.24", "@types/jest": "^27.0.1",
"@types/lodash-es": "^4.17.4", "@types/lodash-es": "^4.17.4",
"@types/mockjs": "^1.0.4", "@types/mockjs": "^1.0.4",
"@types/node": "^16.4.10", "@types/node": "^16.7.1",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.4.1", "@types/qrcode": "^1.4.1",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@types/sortablejs": "^1.10.7", "@types/sortablejs": "^1.10.7",
"@typescript-eslint/eslint-plugin": "^4.29.0", "@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.0", "@typescript-eslint/parser": "^4.29.3",
"@vitejs/plugin-legacy": "^1.5.0", "@vitejs/plugin-legacy": "^1.5.1",
"@vitejs/plugin-vue": "^1.3.0", "@vitejs/plugin-vue": "^1.4.0",
"@vitejs/plugin-vue-jsx": "^1.1.7", "@vitejs/plugin-vue-jsx": "^1.1.7",
"@vue/compiler-sfc": "3.1.5", "@vue/compiler-sfc": "3.2.4",
"@vue/test-utils": "^2.0.0-rc.12", "@vue/test-utils": "^2.0.0-rc.12",
"autoprefixer": "^10.3.1", "autoprefixer": "^10.3.2",
"commitizen": "^4.2.4", "commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.1.1", "conventional-changelog-cli": "^2.1.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
@ -98,17 +98,17 @@
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-define-config": "^1.0.9", "eslint-define-config": "^1.0.9",
"eslint-plugin-jest": "^24.4.0", "eslint-plugin-jest": "^24.4.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-vue": "^7.15.0", "eslint-plugin-vue": "^7.16.0",
"esno": "^0.8.0", "esno": "^0.9.1",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"http-server": "^0.12.3", "http-server": "^13.0.1",
"husky": "^7.0.1", "husky": "^7.0.1",
"inquirer": "^8.1.2", "inquirer": "^8.1.2",
"is-ci": "^3.0.0", "is-ci": "^3.0.0",
"jest": "^27.0.6", "jest": "^27.0.6",
"less": "^4.1.1", "less": "^4.1.1",
"lint-staged": "^11.1.1", "lint-staged": "^11.1.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"postcss": "^8.3.6", "postcss": "^8.3.6",
"prettier": "^2.3.2", "prettier": "^2.3.2",
@ -119,27 +119,27 @@
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^22.0.0", "stylelint-config-standard": "^22.0.0",
"stylelint-order": "^4.1.0", "stylelint-order": "^4.1.0",
"ts-jest": "^27.0.4", "ts-jest": "^27.0.5",
"ts-node": "^10.1.0", "ts-node": "^10.2.1",
"typescript": "4.3.5", "typescript": "4.3.5",
"vite": "2.4.4", "vite": "2.5.0",
"vite-plugin-compression": "^0.3.3", "vite-plugin-compression": "^0.3.5",
"vite-plugin-html": "^2.0.7", "vite-plugin-html": "^2.1.0",
"vite-plugin-imagemin": "^0.4.3", "vite-plugin-imagemin": "^0.4.5",
"vite-plugin-mock": "^2.9.4", "vite-plugin-mock": "^2.9.6",
"vite-plugin-purge-icons": "^0.7.0", "vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-pwa": "^0.9.3", "vite-plugin-pwa": "^0.11.0",
"vite-plugin-style-import": "^1.1.0", "vite-plugin-style-import": "^1.2.1",
"vite-plugin-svg-icons": "^1.0.3", "vite-plugin-svg-icons": "^1.0.4",
"vite-plugin-theme": "^0.8.1", "vite-plugin-theme": "^0.8.1",
"vite-plugin-windicss": "^1.2.7", "vite-plugin-windicss": "^1.2.8",
"vue-eslint-parser": "^7.10.0", "vue-eslint-parser": "^7.10.0",
"vue-tsc": "^0.2.2" "vue-tsc": "^0.3.0"
}, },
"resolutions": { "resolutions": {
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it", "//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it",
"bin-wrapper": "npm:bin-wrapper-china", "bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.55.1" "rollup": "^2.56.3"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -7,7 +7,7 @@ module.exports = {
singleQuote: true, singleQuote: true,
quoteProps: 'as-needed', quoteProps: 'as-needed',
bracketSpacing: true, bracketSpacing: true,
trailingComma: 'es5', trailingComma: 'all',
jsxBracketSameLine: false, jsxBracketSameLine: false,
jsxSingleQuote: false, jsxSingleQuote: false,
arrowParens: 'always', arrowParens: 'always',
@ -16,5 +16,4 @@ module.exports = {
proseWrap: 'never', proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict', htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto', endOfLine: 'auto',
rangeStart: 0,
}; };

View File

@ -6,23 +6,15 @@
</ConfigProvider> </ConfigProvider>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { ConfigProvider } from 'ant-design-vue'; import { ConfigProvider } from 'ant-design-vue';
import { AppProvider } from '/@/components/Application'; import { AppProvider } from '/@/components/Application';
import { useTitle } from '/@/hooks/web/useTitle'; import { useTitle } from '/@/hooks/web/useTitle';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
export default defineComponent({ // support Multi-language
name: 'App', const { getAntdLocale } = useLocale();
components: { ConfigProvider, AppProvider },
setup() {
useTitle();
// support Multi-language // Listening to page changes and dynamically changing site titles
const { getAntdLocale } = useLocale(); useTitle();
return { getAntdLocale };
},
});
</script> </script>

View File

@ -10,13 +10,13 @@ const { uploadUrl = '' } = useGlobSetting();
*/ */
export function uploadApi( export function uploadApi(
params: UploadFileParams, params: UploadFileParams,
onUploadProgress: (progressEvent: ProgressEvent) => void onUploadProgress: (progressEvent: ProgressEvent) => void,
) { ) {
return defHttp.uploadFile<UploadApiResult>( return defHttp.uploadFile<UploadApiResult>(
{ {
url: uploadUrl, url: uploadUrl,
onUploadProgress, onUploadProgress,
}, },
params params,
); );
} }

View File

@ -22,7 +22,7 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
}, },
{ {
errorMessageMode: mode, errorMessageMode: mode,
} },
); );
} }

View File

@ -1,12 +1,12 @@
<template> <template>
<div v-if="getShowDarkModeToggle" :class="getClass" @click="toggleDarkMode"> <div v-if="getShowDarkModeToggle" :class="getClass" @click="toggleDarkMode">
<div :class="`${prefixCls}-inner`"> </div> <div :class="`${prefixCls}-inner`"></div>
<SvgIcon size="14" name="sun" /> <SvgIcon size="14" name="sun" />
<SvgIcon size="14" name="moon" /> <SvgIcon size="14" name="moon" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, computed, unref } from 'vue'; import { computed, unref } from 'vue';
import { SvgIcon } from '/@/components/Icon'; import { SvgIcon } from '/@/components/Icon';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
@ -14,39 +14,25 @@
import { updateDarkTheme } from '/@/logics/theme/dark'; import { updateDarkTheme } from '/@/logics/theme/dark';
import { ThemeEnum } from '/@/enums/appEnum'; import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({ const { prefixCls } = useDesign('dark-switch');
name: 'DarkModeToggle', const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
components: { SvgIcon },
setup() {
const { prefixCls } = useDesign('dark-switch');
const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK); const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
const getClass = computed(() => [ const getClass = computed(() => [
prefixCls, prefixCls,
{ {
[`${prefixCls}--dark`]: unref(isDark), [`${prefixCls}--dark`]: unref(isDark),
},
]);
function toggleDarkMode() {
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
setDarkMode(darkMode);
updateDarkTheme(darkMode);
updateHeaderBgColor();
updateSidebarBgColor();
}
return {
getClass,
isDark,
prefixCls,
toggleDarkMode,
getShowDarkModeToggle,
};
}, },
}); ]);
function toggleDarkMode() {
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
setDarkMode(darkMode);
updateDarkTheme(darkMode);
updateHeaderBgColor();
updateSidebarBgColor();
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-dark-switch'; @prefix-cls: ~'@{namespace}-dark-switch';

View File

@ -17,16 +17,16 @@
</span> </span>
</Dropdown> </Dropdown>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { LocaleType } from '/#/config'; import type { LocaleType } from '/#/config';
import type { DropMenu } from '/@/components/Dropdown'; import type { DropMenu } from '/@/components/Dropdown';
import { defineComponent, ref, watchEffect, unref, computed } from 'vue'; import { ref, watchEffect, unref, computed } from 'vue';
import { Dropdown } from '/@/components/Dropdown'; import { Dropdown } from '/@/components/Dropdown';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { localeList } from '/@/settings/localeSetting'; import { localeList } from '/@/settings/localeSetting';
const props = { const props = defineProps({
/** /**
* Whether to display text * Whether to display text
*/ */
@ -35,45 +35,36 @@
* Whether to refresh the interface when changing * Whether to refresh the interface when changing
*/ */
reload: { type: Boolean }, reload: { type: Boolean },
};
export default defineComponent({
name: 'AppLocalPicker',
components: { Dropdown, Icon },
props,
setup(props) {
const selectedKeys = ref<string[]>([]);
const { changeLocale, getLocale } = useLocale();
const getLocaleText = computed(() => {
const key = selectedKeys.value[0];
if (!key) {
return '';
}
return localeList.find((item) => item.event === key)?.text;
});
watchEffect(() => {
selectedKeys.value = [unref(getLocale)];
});
async function toggleLocale(lang: LocaleType | string) {
await changeLocale(lang as LocaleType);
selectedKeys.value = [lang as string];
props.reload && location.reload();
}
function handleMenuEvent(menu: DropMenu) {
if (unref(getLocale) === menu.event) {
return;
}
toggleLocale(menu.event as string);
}
return { localeList, handleMenuEvent, selectedKeys, getLocaleText };
},
}); });
const selectedKeys = ref<string[]>([]);
const { changeLocale, getLocale } = useLocale();
const getLocaleText = computed(() => {
const key = selectedKeys.value[0];
if (!key) {
return '';
}
return localeList.find((item) => item.event === key)?.text;
});
watchEffect(() => {
selectedKeys.value = [unref(getLocale)];
});
async function toggleLocale(lang: LocaleType | string) {
await changeLocale(lang as LocaleType);
selectedKeys.value = [lang as string];
props.reload && location.reload();
}
function handleMenuEvent(menu: DropMenu) {
if (unref(getLocale) === menu.event) {
return;
}
toggleLocale(menu.event as string);
}
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -10,8 +10,8 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, computed, unref } from 'vue'; import { computed, unref } from 'vue';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
@ -19,11 +19,11 @@
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
const props = { const props = defineProps({
/** /**
* The theme of the current parent component * The theme of the current parent component
*/ */
theme: { type: String, validator: (v) => ['light', 'dark'].includes(v) }, theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
/** /**
* Whether to show title * Whether to show title
*/ */
@ -32,45 +32,30 @@
* The title is also displayed when the menu is collapsed * The title is also displayed when the menu is collapsed
*/ */
alwaysShowTitle: { type: Boolean }, alwaysShowTitle: { type: Boolean },
};
export default defineComponent({
name: 'AppLogo',
props: props,
setup(props) {
const { prefixCls } = useDesign('app-logo');
const { getCollapsedShowTitle } = useMenuSetting();
const userStore = useUserStore();
const { title } = useGlobSetting();
const go = useGo();
const getAppLogoClass = computed(() => [
prefixCls,
props.theme,
{ 'collapsed-show-title': unref(getCollapsedShowTitle) },
]);
const getTitleClass = computed(() => [
`${prefixCls}__title`,
{
'xs:opacity-0': !props.alwaysShowTitle,
},
]);
function goHome() {
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
}
return {
getAppLogoClass,
getTitleClass,
getCollapsedShowTitle,
goHome,
title,
prefixCls,
};
},
}); });
const { prefixCls } = useDesign('app-logo');
const { getCollapsedShowTitle } = useMenuSetting();
const userStore = useUserStore();
const { title } = useGlobSetting();
const go = useGo();
const getAppLogoClass = computed(() => [
prefixCls,
props.theme,
{ 'collapsed-show-title': unref(getCollapsedShowTitle) },
]);
const getTitleClass = computed(() => [
`${prefixCls}__title`,
{
'xs:opacity-0': !props.alwaysShowTitle,
},
]);
function goHome() {
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-logo'; @prefix-cls: ~'@{namespace}-app-logo';

View File

@ -10,20 +10,12 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import AppSearchKeyItem from './AppSearchKeyItem.vue'; import AppSearchKeyItem from './AppSearchKeyItem.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({ const { prefixCls } = useDesign('app-search-footer');
name: 'AppSearchFooter', const { t } = useI18n();
components: { AppSearchKeyItem },
setup() {
const { prefixCls } = useDesign('app-search-footer');
const { t } = useI18n();
return { prefixCls, t };
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-search-footer'; @prefix-cls: ~'@{namespace}-app-search-footer';

View File

@ -3,11 +3,9 @@
<Icon :icon="icon" /> <Icon :icon="icon" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
export default defineComponent({ defineProps({
components: { Icon }, icon: String,
props: { icon: String },
}); });
</script> </script>

View File

@ -56,85 +56,62 @@
</transition> </transition>
</Teleport> </Teleport>
</template> </template>
<script lang="ts">
import { defineComponent, computed, unref, ref, watch, nextTick } from 'vue'; <script lang="ts" setup>
import { computed, unref, ref, watch, nextTick } from 'vue';
import { SearchOutlined } from '@ant-design/icons-vue'; import { SearchOutlined } from '@ant-design/icons-vue';
import AppSearchFooter from './AppSearchFooter.vue'; import AppSearchFooter from './AppSearchFooter.vue';
import Icon from '/@/components/Icon'; import Icon from '/@/components/Icon';
import clickOutside from '/@/directives/clickOutside'; // @ts-ignore
import vClickOutside from '/@/directives/clickOutside';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useRefs } from '/@/hooks/core/useRefs'; import { useRefs } from '/@/hooks/core/useRefs';
import { useMenuSearch } from './useMenuSearch'; import { useMenuSearch } from './useMenuSearch';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useAppInject } from '/@/hooks/web/useAppInject'; import { useAppInject } from '/@/hooks/web/useAppInject';
const props = { const props = defineProps({
visible: { type: Boolean }, visible: { type: Boolean },
};
export default defineComponent({
name: 'AppSearchModal',
components: { Icon, SearchOutlined, AppSearchFooter },
directives: {
clickOutside,
},
props,
emits: ['close'],
setup(props, { emit }) {
const scrollWrap = ref<ElRef>(null);
const inputRef = ref<Nullable<HTMLElement>>(null);
const { t } = useI18n();
const { prefixCls } = useDesign('app-search-modal');
const [refs, setRefs] = useRefs();
const { getIsMobile } = useAppInject();
const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
useMenuSearch(refs, scrollWrap, emit);
const getIsNotData = computed(() => !keyword || unref(searchResult).length === 0);
const getClass = computed(() => {
return [
prefixCls,
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
];
});
watch(
() => props.visible,
(visible: boolean) => {
visible &&
nextTick(() => {
unref(inputRef)?.focus();
});
}
);
function handleClose() {
searchResult.value = [];
emit('close');
}
return {
t,
prefixCls,
getClass,
handleSearch,
searchResult,
activeIndex,
getIsNotData,
handleEnter,
setRefs,
scrollWrap,
handleMouseenter,
handleClose,
inputRef,
};
},
}); });
const emit = defineEmits(['close']);
const scrollWrap = ref(null);
const inputRef = ref<Nullable<HTMLElement>>(null);
const { t } = useI18n();
const { prefixCls } = useDesign('app-search-modal');
const [refs, setRefs] = useRefs();
const { getIsMobile } = useAppInject();
const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
useMenuSearch(refs, scrollWrap, emit);
const getIsNotData = computed(() => !keyword || unref(searchResult).length === 0);
const getClass = computed(() => {
return [
prefixCls,
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
];
});
watch(
() => props.visible,
(visible: boolean) => {
visible &&
nextTick(() => {
unref(inputRef)?.focus();
});
},
);
function handleClose() {
searchResult.value = [];
emit('close');
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-search-modal'; @prefix-cls: ~'@{namespace}-app-search-modal';

View File

@ -7,12 +7,12 @@
<Icon icon="ion:chevron-forward" :style="$attrs.iconStyle" /> <Icon icon="ion:chevron-forward" :style="$attrs.iconStyle" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
const props = { const props = defineProps({
/** /**
* Arrow expand state * Arrow expand state
*/ */
@ -29,31 +29,22 @@
* Cancel padding/margin for inline * Cancel padding/margin for inline
*/ */
inset: { type: Boolean }, inset: { type: Boolean },
}; });
export default defineComponent({ const { prefixCls } = useDesign('basic-arrow');
name: 'BasicArrow',
components: { Icon },
props,
setup(props) {
const { prefixCls } = useDesign('basic-arrow');
// get component class // get component class
const getClass = computed(() => { const getClass = computed(() => {
const { expand, up, down, inset } = props; const { expand, up, down, inset } = props;
return [ return [
prefixCls, prefixCls,
{ {
[`${prefixCls}--active`]: expand, [`${prefixCls}--active`]: expand,
up, up,
inset, inset,
down, down,
}, },
]; ];
});
return { getClass };
},
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -47,7 +47,7 @@
const { prefixCls } = useDesign('basic-help'); const { prefixCls } = useDesign('basic-help');
const getTooltipStyle = computed( const getTooltipStyle = computed(
(): CSSProperties => ({ color: props.color, fontSize: props.fontSize }) (): CSSProperties => ({ color: props.color, fontSize: props.fontSize }),
); );
const getOverlayStyle = computed((): CSSProperties => ({ maxWidth: props.maxWidth })); const getOverlayStyle = computed((): CSSProperties => ({ maxWidth: props.maxWidth }));

View File

@ -4,13 +4,13 @@
<BasicHelp :class="`${prefixCls}-help`" v-if="helpMessage" :text="helpMessage" /> <BasicHelp :class="`${prefixCls}-help`" v-if="helpMessage" :text="helpMessage" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { defineComponent, computed } from 'vue'; import { useSlots, computed } from 'vue';
import BasicHelp from './BasicHelp.vue'; import BasicHelp from './BasicHelp.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
const props = { const props = defineProps({
/** /**
* Help text list or string * Help text list or string
* @default: '' * @default: ''
@ -29,24 +29,15 @@
* @default: false * @default: false
*/ */
normal: { type: Boolean }, normal: { type: Boolean },
};
export default defineComponent({
name: 'BasicTitle',
components: { BasicHelp },
props,
setup(props, { slots }) {
const { prefixCls } = useDesign('basic-title');
const getClass = computed(() => [
prefixCls,
{ [`${prefixCls}-show-span`]: props.span && slots.default },
{ [`${prefixCls}-normal`]: props.normal },
]);
return { prefixCls, getClass };
},
}); });
const { prefixCls } = useDesign('basic-title');
const slots = useSlots();
const getClass = computed(() => [
prefixCls,
{ [`${prefixCls}-show-span`]: props.span && slots.default },
{ [`${prefixCls}-normal`]: props.normal },
]);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-basic-title'; @prefix-cls: ~'@{namespace}-basic-title';

View File

@ -2,40 +2,39 @@
<Button v-bind="getBindValue" :class="getButtonClass" @click="onClick"> <Button v-bind="getBindValue" :class="getButtonClass" @click="onClick">
<template #default="data"> <template #default="data">
<Icon :icon="preIcon" v-if="preIcon" :size="iconSize" /> <Icon :icon="preIcon" v-if="preIcon" :size="iconSize" />
<slot v-bind="data"></slot> <slot v-bind="data || {}"></slot>
<Icon :icon="postIcon" v-if="postIcon" :size="iconSize" /> <Icon :icon="postIcon" v-if="postIcon" :size="iconSize" />
</template> </template>
</Button> </Button>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed, unref } from 'vue'; import { defineComponent } from 'vue';
export default defineComponent({
name: 'AButton',
inheritAttrs: false,
});
</script>
<script lang="ts" setup>
import { computed, unref } from 'vue';
import { Button } from 'ant-design-vue'; import { Button } from 'ant-design-vue';
import Icon from '/@/components/Icon/src/Icon.vue'; import Icon from '/@/components/Icon/src/Icon.vue';
import { buttonProps } from './props'; import { buttonProps } from './props';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
export default defineComponent({ const props = defineProps(buttonProps);
name: 'AButton', // get component class
components: { Button, Icon }, const attrs = useAttrs({ excludeDefaultKeys: false });
inheritAttrs: false, const getButtonClass = computed(() => {
props: buttonProps, const { color, disabled } = props;
setup(props) { return [
// get component class {
const attrs = useAttrs({ excludeDefaultKeys: false }); [`ant-btn-${color}`]: !!color,
const getButtonClass = computed(() => { [`is-disabled`]: disabled,
const { color, disabled } = props; },
return [ ];
{
[`ant-btn-${color}`]: !!color,
[`is-disabled`]: disabled,
},
];
});
// get inherit binding value
const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
return { getBindValue, getButtonClass };
},
}); });
// get inherit binding value
const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
</script> </script>

View File

@ -20,7 +20,6 @@
export default defineComponent({ export default defineComponent({
name: 'PopButton', name: 'PopButton',
components: { Popconfirm, BasicButton },
inheritAttrs: false, inheritAttrs: false,
props, props,
setup(props, { slots }) { setup(props, { slots }) {
@ -34,13 +33,13 @@
okText: t('common.okText'), okText: t('common.okText'),
cancelText: t('common.cancelText'), cancelText: t('common.cancelText'),
}, },
{ ...props, ...unref(attrs) } { ...props, ...unref(attrs) },
); );
}); });
return () => { return () => {
const bindValues = omit(unref(getBindValues), 'icon'); const bindValues = omit(unref(getBindValues), 'icon');
const btnBind = omit(bindValues, 'title'); const btnBind = omit(bindValues, 'title') as Recordable;
if (btnBind.disabled) btnBind.color = ''; if (btnBind.disabled) btnBind.color = '';
const Button = h(BasicButton, btnBind, extendSlots(slots)); const Button = h(BasicButton, btnBind, extendSlots(slots));

View File

@ -3,24 +3,17 @@
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { onClickOutside } from '@vueuse/core'; import { onClickOutside } from '@vueuse/core';
export default defineComponent({ const emit = defineEmits(['mounted', 'clickOutside']);
name: 'ClickOutSide', const wrap = ref<ElRef>(null);
emits: ['mounted', 'clickOutside'],
setup(_, { emit }) {
const wrap = ref<ElRef>(null);
onClickOutside(wrap, () => { onClickOutside(wrap, () => {
emit('clickOutside'); emit('clickOutside');
}); });
onMounted(() => { onMounted(() => {
emit('mounted'); emit('mounted');
});
return { wrap };
},
}); });
</script> </script>

View File

@ -8,45 +8,47 @@
/> />
</div> </div>
</template> </template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
import { isString } from '/@/utils/is';
<script lang="ts">
const MODE = { const MODE = {
JSON: 'application/json', JSON: 'application/json',
html: 'htmlmixed', html: 'htmlmixed',
js: 'javascript', js: 'javascript',
}; };
</script>
<script lang="ts" setup>
import { computed } from 'vue';
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
import { isString } from '/@/utils/is';
const props = { const props = defineProps({
value: { type: [Object, String] as PropType<Record<string, any> | string> }, value: { type: [Object, String] as PropType<Record<string, any> | string> },
mode: { type: String, default: MODE.JSON }, mode: { type: String, default: MODE.JSON },
readonly: { type: Boolean }, readonly: { type: Boolean },
}; autoFormat: { type: Boolean, default: true },
export default defineComponent({
name: 'CodeEditor',
components: { CodeMirrorEditor },
props,
emits: ['change', 'update:value'],
setup(props, { emit }) {
const getValue = computed(() => {
const { value, mode } = props;
if (mode !== MODE.JSON) {
return value as string;
}
return isString(value)
? JSON.stringify(JSON.parse(value), null, 2)
: JSON.stringify(value, null, 2);
});
function handleValueChange(v) {
emit('update:value', v);
emit('change', v);
}
return { handleValueChange, getValue };
},
}); });
const emit = defineEmits(['change', 'update:value', 'format-error']);
const getValue = computed(() => {
const { value, mode, autoFormat } = props;
if (!autoFormat || mode !== MODE.JSON) {
return value as string;
}
let result = value;
if (isString(value)) {
try {
result = JSON.parse(value);
} catch (e) {
emit('format-error', value);
return value as string;
}
}
return JSON.stringify(result, null, 2);
});
function handleValueChange(v) {
emit('update:value', v);
emit('change', v);
}
</script> </script>

View File

@ -1,18 +1,9 @@
<template> <template>
<div class="relative !h-full w-full overflow-hidden" ref="el"> </div> <div class="relative !h-full w-full overflow-hidden" ref="el"></div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { import { ref, onMounted, onUnmounted, watchEffect, watch, unref, nextTick } from 'vue';
ref,
onMounted,
onUnmounted,
watchEffect,
watch,
defineComponent,
unref,
nextTick,
} from 'vue';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
import { useAppStore } from '/@/store/modules/app'; import { useAppStore } from '/@/store/modules/app';
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn'; import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
@ -26,95 +17,89 @@
import 'codemirror/mode/css/css'; import 'codemirror/mode/css/css';
import 'codemirror/mode/htmlmixed/htmlmixed'; import 'codemirror/mode/htmlmixed/htmlmixed';
const props = { const props = defineProps({
mode: { type: String, default: 'application/json' }, mode: { type: String, default: 'application/json' },
value: { type: String, default: '' }, value: { type: String, default: '' },
readonly: { type: Boolean, default: false }, readonly: { type: Boolean, default: false },
}; });
export default defineComponent({ const emit = defineEmits(['change']);
props,
emits: ['change'],
setup(props, { emit }) {
const el = ref();
let editor: Nullable<CodeMirror.Editor>;
const debounceRefresh = useDebounceFn(refresh, 100); const el = ref();
const appStore = useAppStore(); let editor: Nullable<CodeMirror.Editor>;
watch( const debounceRefresh = useDebounceFn(refresh, 100);
() => props.value, const appStore = useAppStore();
async (value) => {
await nextTick();
const oldValue = editor?.getValue();
if (value !== oldValue) {
editor?.setValue(value ? value : '');
}
},
{ flush: 'post' }
);
watchEffect(() => { watch(
editor?.setOption('mode', props.mode); () => props.value,
}); async (value) => {
await nextTick();
watch( const oldValue = editor?.getValue();
() => appStore.getDarkMode, if (value !== oldValue) {
async () => { editor?.setValue(value ? value : '');
setTheme();
},
{
immediate: true,
}
);
function setTheme() {
unref(editor)?.setOption(
'theme',
appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight'
);
} }
function refresh() {
editor?.refresh();
}
async function init() {
const addonOptions = {
autoCloseBrackets: true,
autoCloseTags: true,
foldGutter: true,
gutters: ['CodeMirror-linenumbers'],
};
editor = CodeMirror(el.value!, {
value: '',
mode: props.mode,
readOnly: props.readonly,
tabSize: 2,
theme: 'material-palenight',
lineWrapping: true,
lineNumbers: true,
...addonOptions,
});
editor?.setValue(props.value);
setTheme();
editor?.on('change', () => {
emit('change', editor?.getValue());
});
}
onMounted(async () => {
await nextTick();
init();
useWindowSizeFn(debounceRefresh);
});
onUnmounted(() => {
editor = null;
});
return { el };
}, },
{ flush: 'post' },
);
watchEffect(() => {
editor?.setOption('mode', props.mode);
});
watch(
() => appStore.getDarkMode,
async () => {
setTheme();
},
{
immediate: true,
},
);
function setTheme() {
unref(editor)?.setOption(
'theme',
appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight',
);
}
function refresh() {
editor?.refresh();
}
async function init() {
const addonOptions = {
autoCloseBrackets: true,
autoCloseTags: true,
foldGutter: true,
gutters: ['CodeMirror-linenumbers'],
};
editor = CodeMirror(el.value!, {
value: '',
mode: props.mode,
readOnly: props.readonly,
tabSize: 2,
theme: 'material-palenight',
lineWrapping: true,
lineNumbers: true,
...addonOptions,
});
editor?.setValue(props.value);
setTheme();
editor?.on('change', () => {
emit('change', editor?.getValue());
});
}
onMounted(async () => {
await nextTick();
init();
useWindowSizeFn(debounceRefresh);
});
onUnmounted(() => {
editor = null;
}); });
</script> </script>

View File

@ -2,13 +2,11 @@
<vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" /> <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" />
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import VueJsonPretty from 'vue-json-pretty'; import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css'; import 'vue-json-pretty/lib/styles.css';
import { defineComponent } from 'vue';
export default defineComponent({ defineProps({
name: 'JsonPreview', data: Object,
components: { VueJsonPretty },
props: { data: Object },
}); });
</script> </script>

View File

@ -54,7 +54,7 @@
return; return;
} }
nextTick(() => { nextTick(() => {
const wrap = unref(scrollbar.wrap); const wrap = unref(scrollbar.wrap) as any;
if (!wrap) { if (!wrap) {
return; return;
} }

View File

@ -22,9 +22,9 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
// component // component
import { Skeleton } from 'ant-design-vue'; import { Skeleton } from 'ant-design-vue';
import { CollapseTransition } from '/@/components/Transition'; import { CollapseTransition } from '/@/components/Transition';
@ -34,7 +34,7 @@
import { useTimeoutFn } from '/@/hooks/core/useTimeout'; import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
const props = { const props = defineProps({
title: { type: String, default: '' }, title: { type: String, default: '' },
loading: { type: Boolean }, loading: { type: Boolean },
/** /**
@ -57,39 +57,22 @@
* Delayed loading time * Delayed loading time
*/ */
lazyTime: { type: Number, default: 0 }, lazyTime: { type: Number, default: 0 },
};
export default defineComponent({
name: 'CollapseContainer',
components: {
Skeleton,
CollapseHeader,
CollapseTransition,
},
props,
setup(props) {
const show = ref(true);
const { prefixCls } = useDesign('collapse-container');
/**
* @description: Handling development events
*/
function handleExpand() {
show.value = !show.value;
if (props.triggerWindowResize) {
// 200 milliseconds here is because the expansion has animation,
useTimeoutFn(triggerWindowResize, 200);
}
}
return {
show,
handleExpand,
prefixCls,
};
},
}); });
const show = ref(true);
const { prefixCls } = useDesign('collapse-container');
/**
* @description: Handling development events
*/
function handleExpand() {
show.value = !show.value;
if (props.triggerWindowResize) {
// 200 milliseconds here is because the expansion has animation,
useTimeoutFn(triggerWindowResize, 200);
}
}
</script> </script>
<style lang="less"> <style lang="less">
@prefix-cls: ~'@{namespace}-collapse-container'; @prefix-cls: ~'@{namespace}-collapse-container';

View File

@ -46,7 +46,7 @@
name: 'ContextMenu', name: 'ContextMenu',
props, props,
setup(props) { setup(props) {
const wrapRef = ref<ElRef>(null); const wrapRef = ref(null);
const showRef = ref(false); const showRef = ref(false);
const getStyle = computed((): CSSProperties => { const getStyle = computed((): CSSProperties => {

View File

@ -4,7 +4,7 @@
<CountButton :size="size" :count="count" :value="state" :beforeStartFunc="sendCodeApi" /> <CountButton :size="size" :count="count" :value="state" :beforeStartFunc="sendCodeApi" />
</template> </template>
<template #[item]="data" v-for="item in Object.keys($slots).filter((k) => k !== 'addonAfter')"> <template #[item]="data" v-for="item in Object.keys($slots).filter((k) => k !== 'addonAfter')">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</a-input> </a-input>
</template> </template>

View File

@ -122,10 +122,12 @@
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
type apiFunParams = { file: Blob; name: string; filename: string };
const props = { const props = {
circled: { type: Boolean, default: true }, circled: { type: Boolean, default: true },
uploadApi: { uploadApi: {
type: Function as PropType<({ file: Blob, name: string, filename: string }) => Promise<any>>, type: Function as PropType<(params: apiFunParams) => Promise<any>>,
}, },
}; };

View File

@ -77,7 +77,7 @@
const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) })); const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) }));
const getImageWrapperStyle = computed( const getImageWrapperStyle = computed(
(): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) }) (): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) }),
); );
watchEffect(() => { watchEffect(() => {
@ -88,7 +88,7 @@
() => sourceValue.value, () => sourceValue.value,
(v: string) => { (v: string) => {
emit('update:value', v); emit('update:value', v);
} },
); );
function handleUploadSuccess({ source }) { function handleUploadSuccess({ source }) {
@ -103,7 +103,7 @@
t, t,
prefixCls, prefixCls,
register, register,
openModal, openModal: openModal as any,
getIconWidth, getIconWidth,
sourceValue, sourceValue,
getClass, getClass,

View File

@ -14,7 +14,7 @@ export interface DescItem {
// render // render
render?: ( render?: (
val: any, val: any,
data: Recordable data: Recordable,
) => VNode | undefined | JSX.Element | Element | string | number; ) => VNode | undefined | JSX.Element | Element | string | number;
} }

View File

@ -25,7 +25,7 @@
</ScrollContainer> </ScrollContainer>
<DrawerFooter v-bind="getProps" @close="onClose" @ok="handleOk" :height="getFooterHeight"> <DrawerFooter v-bind="getProps" @close="onClose" @ok="handleOk" :height="getFooterHeight">
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</DrawerFooter> </DrawerFooter>
</Drawer> </Drawer>
@ -139,7 +139,7 @@
(newVal, oldVal) => { (newVal, oldVal) => {
if (newVal !== oldVal) visibleRef.value = newVal; if (newVal !== oldVal) visibleRef.value = newVal;
}, },
{ deep: true } { deep: true },
); );
watch( watch(
@ -149,7 +149,7 @@
emit('visible-change', visible); emit('visible-change', visible);
instance && drawerInstance.emitVisible?.(visible, instance.uid); instance && drawerInstance.emitVisible?.(visible, instance.uid);
}); });
} },
); );
// Cancel event // Cancel event
@ -181,9 +181,9 @@
onClose, onClose,
t, t,
prefixCls, prefixCls,
getMergeProps, getMergeProps: getMergeProps as any,
getScrollContentStyle, getScrollContentStyle,
getProps, getProps: getProps as any,
getLoading, getLoading,
getBindValues, getBindValues,
getFooterHeight, getFooterHeight,

View File

@ -8,6 +8,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import type { Ref } from 'vue';
import type { Definition } from '@logicflow/core'; import type { Definition } from '@logicflow/core';
import { defineComponent, ref, onMounted, unref, nextTick, computed, watch } from 'vue'; import { defineComponent, ref, onMounted, unref, nextTick, computed, watch } from 'vue';
import FlowChartToolbar from './FlowChartToolbar.vue'; import FlowChartToolbar from './FlowChartToolbar.vue';
@ -46,10 +47,10 @@
}, },
}, },
setup(props) { setup(props) {
const lfElRef = ref<ElRef>(null); const lfElRef = ref(null);
const graphData = ref<Recordable>({}); const graphData = ref({});
const lfInstance = ref<Nullable<LogicFlow>>(null); const lfInstance = ref(null) as Ref<LogicFlow | null>;
const { prefixCls } = useDesign('flow-chart'); const { prefixCls } = useDesign('flow-chart');
const appStore = useAppStore(); const appStore = useAppStore();
@ -78,7 +79,7 @@
() => props.data, () => props.data,
() => { () => {
onRender(); onRender();
} },
); );
// TODO // TODO
@ -93,7 +94,7 @@
() => unref(getFlowOptions), () => unref(getFlowOptions),
(options) => { (options) => {
unref(lfInstance)?.updateEditConfig(options); unref(lfInstance)?.updateEditConfig(options);
} },
); );
// init logicFlow // init logicFlow

View File

@ -19,17 +19,17 @@
:setFormModel="setFormModel" :setFormModel="setFormModel"
> >
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</FormItem> </FormItem>
</template> </template>
<FormAction v-bind="{ ...getProps, ...advanceState }" @toggle-advanced="handleToggleAdvanced"> <FormAction v-bind="getFormActionBindProps" @toggle-advanced="handleToggleAdvanced">
<template <template
#[item]="data" #[item]="data"
v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore', 'advanceAfter']" v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore', 'advanceAfter']"
> >
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</FormAction> </FormAction>
<slot name="formFooter"></slot> <slot name="formFooter"></slot>
@ -62,8 +62,6 @@
import { basicProps } from './props'; import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import type { RowProps } from 'ant-design-vue/lib/grid/Row';
export default defineComponent({ export default defineComponent({
name: 'BasicForm', name: 'BasicForm',
components: { FormItem, Form, Row, FormAction }, components: { FormItem, Form, Row, FormAction },
@ -103,7 +101,7 @@
}); });
// Get uniform row style and Row configuration for the entire form // Get uniform row style and Row configuration for the entire form
const getRow = computed((): RowProps => { const getRow = computed((): Recordable => {
const { baseRowStyle = {}, rowProps } = unref(getProps); const { baseRowStyle = {}, rowProps } = unref(getProps);
return { return {
style: baseRowStyle, style: baseRowStyle,
@ -112,7 +110,7 @@
}); });
const getBindValue = computed( const getBindValue = computed(
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable) () => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
); );
const getSchema = computed((): FormSchema[] => { const getSchema = computed((): FormSchema[] => {
@ -132,7 +130,11 @@
} }
} }
} }
return schemas as FormSchema[]; if (unref(getProps).showAdvancedButton) {
return schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[];
} else {
return schemas as FormSchema[];
}
}); });
const { handleToggleAdvanced } = useAdvanced({ const { handleToggleAdvanced } = useAdvanced({
@ -196,14 +198,14 @@
}, },
{ {
immediate: true, immediate: true,
} },
); );
watch( watch(
() => unref(getProps).schemas, () => unref(getProps).schemas,
(schemas) => { (schemas) => {
resetSchema(schemas ?? []); resetSchema(schemas ?? []);
} },
); );
watch( watch(
@ -220,7 +222,7 @@
initDefault(); initDefault();
isInitedDefaultRef.value = true; isInitedDefaultRef.value = true;
} }
} },
); );
async function setProps(formProps: Partial<FormProps>): Promise<void> { async function setProps(formProps: Partial<FormProps>): Promise<void> {
@ -278,10 +280,12 @@
getProps, getProps,
formElRef, formElRef,
getSchema, getSchema,
formActionType, formActionType: formActionType as any,
setFormModel, setFormModel,
prefixCls,
getFormClass, getFormClass,
getFormActionBindProps: computed(
(): Recordable => ({ ...getProps.value, ...advanceState }),
),
...formActionType, ...formActionType,
}; };
}, },

View File

@ -18,6 +18,7 @@ import {
TreeSelect, TreeSelect,
Slider, Slider,
Rate, Rate,
Divider,
} from 'ant-design-vue'; } from 'ant-design-vue';
import RadioButtonGroup from './components/RadioButtonGroup.vue'; import RadioButtonGroup from './components/RadioButtonGroup.vue';
@ -61,6 +62,7 @@ componentMap.set('IconPicker', IconPicker);
componentMap.set('InputCountDown', CountdownInput); componentMap.set('InputCountDown', CountdownInput);
componentMap.set('Upload', BasicUpload); componentMap.set('Upload', BasicUpload);
componentMap.set('Divider', Divider);
export function add(compName: ComponentType, component: Component) { export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component); componentMap.set(compName, component);

View File

@ -7,7 +7,7 @@
v-model:value="state" v-model:value="state"
> >
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
<template #suffixIcon v-if="loading"> <template #suffixIcon v-if="loading">
<LoadingOutlined spin /> <LoadingOutlined spin />
@ -100,7 +100,7 @@
() => { () => {
!unref(isFirstLoad) && fetch(); !unref(isFirstLoad) && fetch();
}, },
{ deep: true } { deep: true },
); );
async function fetch() { async function fetch() {

View File

@ -1,7 +1,7 @@
<template> <template>
<a-tree-select v-bind="getAttrs" @change="handleChange"> <a-tree-select v-bind="getAttrs" @change="handleChange">
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
<template #suffixIcon v-if="loading"> <template #suffixIcon v-if="loading">
<LoadingOutlined spin /> <LoadingOutlined spin />
@ -46,14 +46,14 @@
() => { () => {
isFirstLoaded.value && fetch(); isFirstLoaded.value && fetch();
}, },
{ deep: true } { deep: true },
); );
watch( watch(
() => props.immediate, () => props.immediate,
(v) => { (v) => {
v && !isFirstLoaded.value && fetch(); v && !isFirstLoaded.value && fetch();
} },
); );
onMounted(() => { onMounted(() => {

View File

@ -105,7 +105,7 @@
{ {
text: t('common.resetText'), text: t('common.resetText'),
}, },
props.resetButtonOptions props.resetButtonOptions,
); );
}); });
@ -114,7 +114,7 @@
{ {
text: t('common.queryText'), text: t('common.queryText'),
}, },
props.submitButtonOptions props.submitButtonOptions,
); );
}); });

View File

@ -5,7 +5,7 @@
import type { ValidationRule } from 'ant-design-vue/lib/form/Form'; import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
import type { TableActionType } from '/@/components/Table'; import type { TableActionType } from '/@/components/Table';
import { defineComponent, computed, unref, toRefs } from 'vue'; import { defineComponent, computed, unref, toRefs } from 'vue';
import { Form, Col } from 'ant-design-vue'; import { Form, Col, Divider } from 'ant-design-vue';
import { componentMap } from '../componentMap'; import { componentMap } from '../componentMap';
import { BasicHelp } from '/@/components/Basic'; import { BasicHelp } from '/@/components/Basic';
import { isBoolean, isFunction, isNull } from '/@/utils/is'; import { isBoolean, isFunction, isNull } from '/@/utils/is';
@ -73,11 +73,17 @@
const getComponentsProps = computed(() => { const getComponentsProps = computed(() => {
const { schema, tableAction, formModel, formActionType } = props; const { schema, tableAction, formModel, formActionType } = props;
const { componentProps = {} } = schema; let { componentProps = {} } = schema;
if (!isFunction(componentProps)) { if (isFunction(componentProps)) {
return componentProps; componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
} }
return componentProps({ schema, tableAction, formModel, formActionType }) ?? {}; if (schema.component === 'Divider') {
componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
orientation: 'left',
plain: true,
});
}
return componentProps as Recordable;
}); });
const getDisable = computed(() => { const getDisable = computed(() => {
@ -177,7 +183,7 @@
} }
const requiredRuleIndex: number = rules.findIndex( const requiredRuleIndex: number = rules.findIndex(
(rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator') (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator'),
); );
if (requiredRuleIndex !== -1) { if (requiredRuleIndex !== -1) {
@ -300,38 +306,46 @@
} }
function renderItem() { function renderItem() {
const { itemProps, slot, render, field, suffix } = props.schema; const { itemProps, slot, render, field, suffix, component } = props.schema;
const { labelCol, wrapperCol } = unref(itemLabelWidthProp); const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
const { colon } = props.formProps; const { colon } = props.formProps;
const getContent = () => { if (component === 'Divider') {
return slot return (
? getSlot(slots, slot, unref(getValues)) <Col span={24}>
: render <Divider {...unref(getComponentsProps)}>{renderLabelHelpMessage()}</Divider>
? render(unref(getValues)) </Col>
: renderComponent(); );
}; } else {
const getContent = () => {
return slot
? getSlot(slots, slot, unref(getValues))
: render
? render(unref(getValues))
: renderComponent();
};
const showSuffix = !!suffix; const showSuffix = !!suffix;
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix; const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
return ( return (
<Form.Item <Form.Item
name={field} name={field}
colon={colon} colon={colon}
class={{ 'suffix-item': showSuffix }} class={{ 'suffix-item': showSuffix }}
{...(itemProps as Recordable)} {...(itemProps as Recordable)}
label={renderLabelHelpMessage()} label={renderLabelHelpMessage()}
rules={handleRules()} rules={handleRules()}
labelCol={labelCol} labelCol={labelCol}
wrapperCol={wrapperCol} wrapperCol={wrapperCol}
> >
<div style="display:flex"> <div style="display:flex">
<div style="flex:1">{getContent()}</div> <div style="flex:1">{getContent()}</div>
{showSuffix && <span class="suffix">{getSuffix}</span>} {showSuffix && <span class="suffix">{getSuffix}</span>}
</div> </div>
</Form.Item> </Form.Item>
); );
}
} }
return () => { return () => {

View File

@ -38,7 +38,7 @@ function genType() {
export function setComponentRuleType( export function setComponentRuleType(
rule: ValidationRule, rule: ValidationRule,
component: ComponentType, component: ComponentType,
valueFormat: string valueFormat: string,
) { ) {
if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) { if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) {
rule.type = valueFormat ? 'string' : 'object'; rule.type = valueFormat ? 'string' : 'object';

View File

@ -58,7 +58,7 @@ export default function ({
debounceUpdateAdvanced(); debounceUpdateAdvanced();
} }
}, },
{ immediate: true } { immediate: true },
); );
function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) { function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
@ -103,7 +103,7 @@ export default function ({
} }
return { isAdvanced: advanceState.isAdvanced, itemColSum }; return { isAdvanced: advanceState.isAdvanced, itemColSum };
} }
if (itemColSum > BASIC_COL_LEN) { if (itemColSum > BASIC_COL_LEN * (unref(getProps).alwaysShowLines || 1)) {
return { isAdvanced: advanceState.isAdvanced, itemColSum }; return { isAdvanced: advanceState.isAdvanced, itemColSum };
} else { } else {
// The first line is always displayed // The first line is always displayed
@ -139,7 +139,7 @@ export default function ({
if (isShow && (colProps || baseColProps)) { if (isShow && (colProps || baseColProps)) {
const { itemColSum: sum, isAdvanced } = getAdvanced( const { itemColSum: sum, isAdvanced } = getAdvanced(
{ ...baseColProps, ...colProps }, { ...baseColProps, ...colProps },
itemColSum itemColSum,
); );
itemColSum = sum || 0; itemColSum = sum || 0;

View File

@ -18,7 +18,7 @@ export function useForm(props?: Props): UseFormReturnType {
const form = unref(formRef); const form = unref(formRef);
if (!form) { if (!form) {
error( error(
'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!' 'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!',
); );
} }
await nextTick(); await nextTick();
@ -44,7 +44,7 @@ export function useForm(props?: Props): UseFormReturnType {
{ {
immediate: true, immediate: true,
deep: true, deep: true,
} },
); );
} }
@ -96,7 +96,7 @@ export function useForm(props?: Props): UseFormReturnType {
appendSchemaByField: async ( appendSchemaByField: async (
schema: FormSchema, schema: FormSchema,
prefixField: string | undefined, prefixField: string | undefined,
first: boolean first: boolean,
) => { ) => {
const form = await getForm(); const form = await getForm();
form.appendSchemaByField(schema, prefixField, first); form.appendSchemaByField(schema, prefixField, first);

View File

@ -149,11 +149,13 @@ export function useFormEvents({
updateData = [...data]; updateData = [...data];
} }
const hasField = updateData.every((item) => Reflect.has(item, 'field') && item.field); const hasField = updateData.every(
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
);
if (!hasField) { if (!hasField) {
error( error(
'All children of the form Schema array that need to be updated must contain the `field` field' 'All children of the form Schema array that need to be updated must contain the `field` field',
); );
return; return;
} }
@ -169,11 +171,13 @@ export function useFormEvents({
updateData = [...data]; updateData = [...data];
} }
const hasField = updateData.every((item) => Reflect.has(item, 'field') && item.field); const hasField = updateData.every(
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
);
if (!hasField) { if (!hasField) {
error( error(
'All children of the form Schema array that need to be updated must contain the `field` field' 'All children of the form Schema array that need to be updated must contain the `field` field',
); );
return; return;
} }

View File

@ -59,6 +59,8 @@ export const basicProps = {
rulesMessageJoinLabel: propTypes.bool.def(true), rulesMessageJoinLabel: propTypes.bool.def(true),
// 超过3行自动折叠 // 超过3行自动折叠
autoAdvancedLine: propTypes.number.def(3), autoAdvancedLine: propTypes.number.def(3),
// 不受折叠影响的行数
alwaysShowLines: propTypes.number.def(1),
// 是否显示操作按钮 // 是否显示操作按钮
showActionButtonGroup: propTypes.bool.def(true), showActionButtonGroup: propTypes.bool.def(true),

View File

@ -37,7 +37,7 @@ export interface FormActionType {
appendSchemaByField: ( appendSchemaByField: (
schema: FormSchema, schema: FormSchema,
prefixField: string | undefined, prefixField: string | undefined,
first?: boolean | undefined first?: boolean | undefined,
) => Promise<void>; ) => Promise<void>;
validateFields: (nameList?: NamePath[]) => Promise<any>; validateFields: (nameList?: NamePath[]) => Promise<any>;
validate: (nameList?: NamePath[]) => Promise<any>; validate: (nameList?: NamePath[]) => Promise<any>;
@ -97,6 +97,8 @@ export interface FormProps {
autoFocusFirstItem?: boolean; autoFocusFirstItem?: boolean;
// Automatically collapse over the specified number of rows // Automatically collapse over the specified number of rows
autoAdvancedLine?: number; autoAdvancedLine?: number;
// Always show lines
alwaysShowLines?: number;
// Whether to show the operation button // Whether to show the operation button
showActionButtonGroup?: boolean; showActionButtonGroup?: boolean;

View File

@ -109,4 +109,5 @@ export type ComponentType =
| 'IconPicker' | 'IconPicker'
| 'Render' | 'Render'
| 'Slider' | 'Slider'
| 'Rate'; | 'Rate'
| 'Divider';

View File

@ -63,7 +63,7 @@
</div> </div>
</div> </div>
<template v-else <template v-else
><div class="p-5"> <Empty /></div> ><div class="p-5"><Empty /></div>
</template> </template>
</template> </template>
@ -121,7 +121,7 @@
copy: propTypes.bool.def(false), copy: propTypes.bool.def(false),
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'), mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
}, },
emits: ['change'], emits: ['change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
const isSvgMode = props.mode === 'svg'; const isSvgMode = props.mode === 'svg';
const icons = isSvgMode ? getSvgIcons() : getIcons(); const icons = isSvgMode ? getSvgIcons() : getIcons();
@ -139,7 +139,7 @@
const { getPaginationList, getTotal, setCurrentPage } = usePagination( const { getPaginationList, getTotal, setCurrentPage } = usePagination(
currentList, currentList,
props.pageSize props.pageSize,
); );
watchEffect(() => { watchEffect(() => {
@ -148,7 +148,10 @@
watch( watch(
() => currentSelect.value, () => currentSelect.value,
(v) => emit('change', v) (v) => {
emit('update:value', v);
return emit('change', v);
},
); );
function handlePageChange(page: number) { function handlePageChange(page: number) {

View File

@ -4,7 +4,7 @@ import type { LoadingProps } from './typing';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
export interface UseLoadingOptions { export interface UseLoadingOptions {
target?: HTMLElement | Ref<ElRef>; target?: any;
props?: Partial<LoadingProps>; props?: Partial<LoadingProps>;
} }
@ -16,7 +16,7 @@ export function useLoading(props: Partial<LoadingProps>): [Fn, Fn, (string) => v
export function useLoading(opt: Partial<UseLoadingOptions>): [Fn, Fn, (string) => void]; export function useLoading(opt: Partial<UseLoadingOptions>): [Fn, Fn, (string) => void];
export function useLoading( export function useLoading(
opt: Partial<LoadingProps> | Partial<UseLoadingOptions> opt: Partial<LoadingProps> | Partial<UseLoadingOptions>,
): [Fn, Fn, (string) => void] { ): [Fn, Fn, (string) => void] {
let props: Partial<LoadingProps>; let props: Partial<LoadingProps>;
let target: HTMLElement | Ref<ElRef> = document.body; let target: HTMLElement | Ref<ElRef> = document.body;
@ -32,7 +32,7 @@ export function useLoading(
const instance = createLoading(props, undefined, true); const instance = createLoading(props, undefined, true);
const open = (): void => { const open = (): void => {
const t = unref(target); const t = unref(target as Ref<ElRef>);
if (!t) return; if (!t) return;
instance.open(t); instance.open(t);
}; };

View File

@ -2,6 +2,7 @@
<div ref="wrapRef"></div> <div ref="wrapRef"></div>
</template> </template>
<script lang="ts"> <script lang="ts">
import type { Ref } from 'vue';
import { import {
defineComponent, defineComponent,
ref, ref,
@ -30,7 +31,7 @@
emits: ['change', 'get', 'update:value'], emits: ['change', 'get', 'update:value'],
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
const wrapRef = ref<ElRef>(null); const wrapRef = ref<ElRef>(null);
const vditorRef = ref<Nullable<Vditor>>(null); const vditorRef = ref(null) as Ref<Nullable<Vditor>>;
const initedRef = ref(false); const initedRef = ref(false);
const modalFn = useModalContext(); const modalFn = useModalContext();
@ -51,7 +52,7 @@
{ {
immediate: true, immediate: true,
flush: 'post', flush: 'post',
} },
); );
watch( watch(
@ -61,7 +62,7 @@
instance.getVditor()?.setValue(v); instance.getVditor()?.setValue(v);
} }
valueRef.value = v; valueRef.value = v;
} },
); );
const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => { const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {

View File

@ -56,15 +56,15 @@
const { prefixCls } = useDesign('basic-menu'); const { prefixCls } = useDesign('basic-menu');
const { items, mode, accordion } = toRefs(props); const { items, mode, accordion } = toRefs(props);
const { getCollapsed, getIsHorizontal, getTopMenuAlign, getSplit } = useMenuSetting(); const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting();
const { currentRoute } = useRouter(); const { currentRoute } = useRouter();
const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys( const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
menuState, menuState,
items, items,
mode, mode as any,
accordion accordion,
); );
const getIsTopMenu = computed(() => { const getIsTopMenu = computed(() => {
@ -114,7 +114,7 @@
() => props.items, () => props.items,
() => { () => {
handleMenuChange(); handleMenuChange();
} },
); );
async function handleMenuClick({ key }: { key: string; keyPath: string[] }) { async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
@ -150,8 +150,6 @@
} }
return { return {
prefixCls,
getIsHorizontal,
handleMenuClick, handleMenuClick,
getInlineCollapseOptions, getInlineCollapseOptions,
getMenuClass, getMenuClass,

View File

@ -4,6 +4,8 @@ import type { PropType } from 'vue';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { ThemeEnum } from '/@/enums/appEnum'; import { ThemeEnum } from '/@/enums/appEnum';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import type { MenuTheme } from 'ant-design-vue';
import type { MenuMode } from 'ant-design-vue/lib/menu/src/interface';
export const basicProps = { export const basicProps = {
items: { items: {
type: Array as PropType<Menu[]>, type: Array as PropType<Menu[]>,
@ -14,7 +16,7 @@ export const basicProps = {
inlineIndent: propTypes.number.def(20), inlineIndent: propTypes.number.def(20),
// 菜单组件的mode属性 // 菜单组件的mode属性
mode: { mode: {
type: String as PropType<MenuModeEnum>, type: String as PropType<MenuMode>,
default: MenuModeEnum.INLINE, default: MenuModeEnum.INLINE,
}, },
@ -22,7 +24,10 @@ export const basicProps = {
type: String as PropType<MenuTypeEnum>, type: String as PropType<MenuTypeEnum>,
default: MenuTypeEnum.MIX, default: MenuTypeEnum.MIX,
}, },
theme: propTypes.string.def(ThemeEnum.DARK), theme: {
type: String as PropType<MenuTheme>,
default: ThemeEnum.DARK,
},
inlineCollapsed: propTypes.bool, inlineCollapsed: propTypes.bool,
mixSider: propTypes.bool, mixSider: propTypes.bool,

View File

@ -14,7 +14,7 @@ export function useOpenKeys(
menuState: MenuState, menuState: MenuState,
menus: Ref<MenuType[]>, menus: Ref<MenuType[]>,
mode: Ref<MenuModeEnum>, mode: Ref<MenuModeEnum>,
accordion: Ref<boolean> accordion: Ref<boolean>,
) { ) {
const { getCollapsed, getIsMixSidebar } = useMenuSetting(); const { getCollapsed, getIsMixSidebar } = useMenuSetting();
@ -37,7 +37,7 @@ export function useOpenKeys(
} }
}, },
16, 16,
!native !native,
); );
} }

View File

@ -20,7 +20,7 @@
<template #footer v-if="!$slots.footer"> <template #footer v-if="!$slots.footer">
<ModalFooter v-bind="getBindValue" @ok="handleOk" @cancel="handleCancel"> <ModalFooter v-bind="getBindValue" @ok="handleOk" @cancel="handleCancel">
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</ModalFooter> </ModalFooter>
</template> </template>
@ -44,7 +44,7 @@
</ModalWrapper> </ModalWrapper>
<template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))"> <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</Modal> </Modal>
</template> </template>
@ -104,7 +104,7 @@
} }
// Custom title component: get title // Custom title component: get title
const getMergeProps = computed((): ModalProps => { const getMergeProps = computed((): Recordable => {
return { return {
...props, ...props,
...(unref(propsRef) as any), ...(unref(propsRef) as any),
@ -118,7 +118,7 @@
}); });
// modal component does not need title and origin buttons // modal component does not need title and origin buttons
const getProps = computed((): ModalProps => { const getProps = computed((): Recordable => {
const opt = { const opt = {
...unref(getMergeProps), ...unref(getMergeProps),
visible: unref(visibleRef), visible: unref(visibleRef),
@ -140,9 +140,9 @@
wrapClassName: unref(getWrapClassName), wrapClassName: unref(getWrapClassName),
}; };
if (unref(fullScreenRef)) { if (unref(fullScreenRef)) {
return omit(attr, 'height'); return omit(attr, ['height', 'title']);
} }
return attr; return omit(attr, 'title');
}); });
const getWrapperHeight = computed(() => { const getWrapperHeight = computed(() => {
@ -169,7 +169,7 @@
}, },
{ {
immediate: false, immediate: false,
} },
); );
// //
@ -212,7 +212,7 @@
extHeightRef.value = height; extHeightRef.value = height;
} }
function handleTitleDbClick(e: ChangeEvent) { function handleTitleDbClick(e) {
if (!props.canFullscreen) return; if (!props.canFullscreen) return;
e.stopPropagation(); e.stopPropagation();
handleFullScreen(e); handleFullScreen(e);

View File

@ -62,7 +62,7 @@
{ {
attributes: true, attributes: true,
subtree: true, subtree: true,
} },
); );
createModalContext({ createModalContext({
@ -89,7 +89,7 @@
} else { } else {
minRealHeightRef.value = realHeightRef.value; minRealHeightRef.value = realHeightRef.value;
} }
} },
); );
onMounted(() => { onMounted(() => {
@ -125,7 +125,7 @@
const modalDom = bodyDom.parentElement && bodyDom.parentElement.parentElement; const modalDom = bodyDom.parentElement && bodyDom.parentElement.parentElement;
if (!modalDom) return; if (!modalDom) return;
const modalRect = getComputedStyle(modalDom).top; const modalRect = getComputedStyle(modalDom as Element).top;
const modalTop = Number.parseInt(modalRect); const modalTop = Number.parseInt(modalRect);
let maxHeight = let maxHeight =
window.innerHeight - window.innerHeight -

View File

@ -5,3 +5,5 @@ import pageWrapper from './src/PageWrapper.vue';
export const PageFooter = withInstall(pageFooter); export const PageFooter = withInstall(pageFooter);
export const PageWrapper = withInstall(pageWrapper); export const PageWrapper = withInstall(pageWrapper);
export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight';

View File

@ -14,7 +14,7 @@
<slot name="headerContent" v-else></slot> <slot name="headerContent" v-else></slot>
</template> </template>
<template #[item]="data" v-for="item in getHeaderSlots"> <template #[item]="data" v-for="item in getHeaderSlots">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</PageHeader> </PageHeader>
@ -33,7 +33,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import type { CSSProperties, PropType } from 'vue'; import { CSSProperties, PropType, provide } from 'vue';
import { defineComponent, computed, watch, ref, unref } from 'vue'; import { defineComponent, computed, watch, ref, unref } from 'vue';
import PageFooter from './PageFooter.vue'; import PageFooter from './PageFooter.vue';
@ -43,6 +43,7 @@
import { omit } from 'lodash-es'; import { omit } from 'lodash-es';
import { PageHeader } from 'ant-design-vue'; import { PageHeader } from 'ant-design-vue';
import { useContentHeight } from '/@/hooks/web/useContentHeight'; import { useContentHeight } from '/@/hooks/web/useContentHeight';
import { PageWrapperFixedHeightKey } from '..';
export default defineComponent({ export default defineComponent({
name: 'PageWrapper', name: 'PageWrapper',
@ -68,6 +69,11 @@
const footerRef = ref(null); const footerRef = ref(null);
const { prefixCls } = useDesign('page-wrapper'); const { prefixCls } = useDesign('page-wrapper');
provide(
PageWrapperFixedHeightKey,
computed(() => props.fixedHeight),
);
const getIsContentFullHeight = computed(() => { const getIsContentFullHeight = computed(() => {
return props.contentFullHeight; return props.contentFullHeight;
}); });
@ -76,7 +82,7 @@
getIsContentFullHeight, getIsContentFullHeight,
wrapperRef, wrapperRef,
[headerRef, footerRef], [headerRef, footerRef],
[contentRef] [contentRef],
); );
setCompensation({ useLayoutFooter: true, elements: [footerRef] }); setCompensation({ useLayoutFooter: true, elements: [footerRef] });
@ -129,7 +135,7 @@
{ {
flush: 'post', flush: 'post',
immediate: true, immediate: true,
} },
); );
return { return {

View File

@ -1,6 +1,5 @@
<script lang="tsx"> <script lang="tsx">
import { defineComponent, ref, unref, computed, reactive, watchEffect } from 'vue'; import { defineComponent, ref, unref, computed, reactive, watchEffect } from 'vue';
import { Props } from './typing';
import { CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vue'; import { CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
import resumeSvg from '/@/assets/svg/preview/resume.svg'; import resumeSvg from '/@/assets/svg/preview/resume.svg';
import rotateSvg from '/@/assets/svg/preview/p-rotate.svg'; import rotateSvg from '/@/assets/svg/preview/p-rotate.svg';
@ -57,7 +56,7 @@
name: 'ImagePreview', name: 'ImagePreview',
props, props,
emits: ['img-load', 'img-error'], emits: ['img-load', 'img-error'],
setup(props: Props, { expose, emit }) { setup(props, { expose, emit }) {
interface stateInfo { interface stateInfo {
scale: number; scale: number;
rotate: number; rotate: number;
@ -117,8 +116,9 @@
} }
const getScaleStep = computed(() => { const getScaleStep = computed(() => {
if (props.scaleStep > 0 && props.scaleStep < 100) { const scaleStep = props?.scaleStep ?? 0;
return props.scaleStep / 100; if (scaleStep ?? (0 > 0 && scaleStep < 100)) {
return scaleStep / 100;
} else { } else {
return imgState.imgScale / 10; return imgState.imgScale / 10;
} }
@ -164,7 +164,7 @@
img.src = url; img.src = url;
img.onload = (e: Event) => { img.onload = (e: Event) => {
if (imgState.currentUrl !== url) { if (imgState.currentUrl !== url) {
const ele: HTMLElement[] = e.composedPath(); const ele: any[] = e.composedPath();
if (props.rememberState) { if (props.rememberState) {
// //
stateMap.set(imgState.currentUrl, { stateMap.set(imgState.currentUrl, {
@ -244,7 +244,7 @@
setRotate: (rotate: number) => { setRotate: (rotate: number) => {
imgState.imgRotate = rotate; imgState.imgRotate = rotate;
}, },
} as PreviewActions); });
// //
function handleChange(direction: 'left' | 'right') { function handleChange(direction: 'left' | 'right') {

View File

@ -56,7 +56,7 @@
setup(props) { setup(props) {
const { prefixCls } = useDesign('image-preview'); const { prefixCls } = useDesign('image-preview');
const getImageList = computed(() => { const getImageList = computed((): any[] => {
const { imageList } = props; const { imageList } = props;
if (!imageList) { if (!imageList) {
return []; return [];

View File

@ -103,7 +103,7 @@
}, },
{ {
deep: true, deep: true,
} },
); );
return { wrapRef, download }; return { wrapRef, download };

View File

@ -7,9 +7,9 @@ export const renderQrCode = ({
canvas, canvas,
content, content,
width = 0, width = 0,
options: params = {} options: params = {},
}: RenderQrCodeParams) => { }: RenderQrCodeParams) => {
const options = cloneDeep(params) const options = cloneDeep(params);
// 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率 // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率
options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content); options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content);

View File

@ -44,7 +44,7 @@ export default defineComponent({
const clickTrackHandler = (e: any) => { const clickTrackHandler = (e: any) => {
const offset = Math.abs( const offset = Math.abs(
e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client] e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client],
); );
const thumbHalf = thumb.value[bar.value.offset] / 2; const thumbHalf = thumb.value[bar.value.offset] / 2;
const thumbPositionPercentage = const thumbPositionPercentage =
@ -104,7 +104,7 @@ export default defineComponent({
move: props.move, move: props.move,
bar: bar.value, bar: bar.value,
}), }),
}) }),
); );
}, },
}); });

View File

@ -75,7 +75,7 @@
items, items,
accordion, accordion,
mixSider, mixSider,
collapse collapse,
); );
const getBindValues = computed(() => ({ ...attrs, ...props })); const getBindValues = computed(() => ({ ...attrs, ...props }));
@ -89,7 +89,7 @@
setOpenKeys(currentRoute.value.path); setOpenKeys(currentRoute.value.path);
} }
}, },
{ immediate: true } { immediate: true },
); );
watch( watch(
@ -100,7 +100,7 @@
} }
setOpenKeys(currentRoute.value.path); setOpenKeys(currentRoute.value.path);
}, },
{ flush: 'post' } { flush: 'post' },
); );
listenerRouteChange((route) => { listenerRouteChange((route) => {

View File

@ -87,7 +87,7 @@
nextTick(() => { nextTick(() => {
updateOpened(); updateOpened();
}); });
} },
); );
function updateOpened() { function updateOpened() {
@ -124,7 +124,7 @@
isRemoveAllPopup, isRemoveAllPopup,
sliceIndex, sliceIndex,
level: 0, level: 0,
props, props: props as any,
}); });
onMounted(() => { onMounted(() => {

View File

@ -98,7 +98,7 @@
active.value = false; active.value = false;
} }
}, },
{ immediate: true } { immediate: true },
); );
return { getClass, prefixCls, getItemStyle, getCollapse, handleClickItem, showTooptip }; return { getClass, prefixCls, getItemStyle, getCollapse, handleClickItem, showTooptip };

View File

@ -286,7 +286,7 @@
if (props.name && Array.isArray(data)) { if (props.name && Array.isArray(data)) {
state.opened = (data as (string | number)[]).includes(props.name); state.opened = (data as (string | number)[]).includes(props.name);
} }
} },
); );
rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => { rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => {

View File

@ -1,9 +1,9 @@
import type { InjectionKey, Ref } from 'vue'; import type { InjectionKey, Ref } from 'vue';
import type { Emitter } from '/@/utils/mitt';
import { createContext, useContext } from '/@/hooks/core/useContext'; import { createContext, useContext } from '/@/hooks/core/useContext';
import mitt from '/@/utils/mitt';
export interface SimpleRootMenuContextProps { export interface SimpleRootMenuContextProps {
rootMenuEmitter: typeof mitt; rootMenuEmitter: Emitter;
activeName: Ref<string | number>; activeName: Ref<string | number>;
} }

View File

@ -15,7 +15,7 @@ export function useOpenKeys(
menus: Ref<MenuType[]>, menus: Ref<MenuType[]>,
accordion: Ref<boolean>, accordion: Ref<boolean>,
mixSider: Ref<boolean>, mixSider: Ref<boolean>,
collapse: Ref<boolean> collapse: Ref<boolean>,
) { ) {
const debounceSetOpenKeys = useDebounceFn(setOpenKeys, 50); const debounceSetOpenKeys = useDebounceFn(setOpenKeys, 50);
async function setOpenKeys(path: string) { async function setOpenKeys(path: string) {
@ -38,7 +38,7 @@ export function useOpenKeys(
menuState.activeSubMenuNames = menuState.openNames; menuState.activeSubMenuNames = menuState.openNames;
}, },
30, 30,
native native,
); );
} }

View File

@ -9,7 +9,7 @@
:disabled="disabled" :disabled="disabled"
> >
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</InputPassword> </InputPassword>
<div :class="`${prefixCls}-bar`"> <div :class="`${prefixCls}-bar`">
@ -59,7 +59,7 @@
() => unref(innerValueRef), () => unref(innerValueRef),
(val) => { (val) => {
emit('change', val); emit('change', val);
} },
); );
return { return {

View File

@ -10,7 +10,7 @@
@advanced-change="redoHeight" @advanced-change="redoHeight"
> >
<template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys"> <template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
</BasicForm> </BasicForm>
@ -22,7 +22,7 @@
@change="handleTableChange" @change="handleTableChange"
> >
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item"> <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data || {}"></slot>
</template> </template>
<template #[`header-${column.dataIndex}`] v-for="column in columns" :key="column.dataIndex"> <template #[`header-${column.dataIndex}`] v-for="column in columns" :key="column.dataIndex">
@ -39,9 +39,10 @@
ColumnChangeParam, ColumnChangeParam,
} from './types/table'; } from './types/table';
import { defineComponent, ref, computed, unref, toRaw } from 'vue'; import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect } from 'vue';
import { Table } from 'ant-design-vue'; import { Table } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form/index'; import { BasicForm, useForm } from '/@/components/Form/index';
import { PageWrapperFixedHeightKey } from '/@/components/Page';
import expandIcon from './components/ExpandIcon'; import expandIcon from './components/ExpandIcon';
import HeaderCell from './components/HeaderCell.vue'; import HeaderCell from './components/HeaderCell.vue';
import { InnerHandlers } from './types/table'; import { InnerHandlers } from './types/table';
@ -64,6 +65,7 @@
import { omit } from 'lodash-es'; import { omit } from 'lodash-es';
import { basicProps } from './props'; import { basicProps } from './props';
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -91,10 +93,10 @@
'columns-change', 'columns-change',
], ],
setup(props, { attrs, emit, slots, expose }) { setup(props, { attrs, emit, slots, expose }) {
const tableElRef = ref<ComponentRef>(null); const tableElRef = ref(null);
const tableData = ref<Recordable[]>([]); const tableData = ref<Recordable[]>([]);
const wrapRef = ref<Nullable<HTMLDivElement>>(null); const wrapRef = ref(null);
const innerPropsRef = ref<Partial<BasicTableProps>>(); const innerPropsRef = ref<Partial<BasicTableProps>>();
const { prefixCls } = useDesign('basic-table'); const { prefixCls } = useDesign('basic-table');
@ -104,6 +106,15 @@
return { ...props, ...unref(innerPropsRef) } as BasicTableProps; return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
}); });
const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
watchEffect(() => {
unref(isFixedHeightPage) &&
props.canResize &&
warn(
"'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)",
);
});
const { getLoading, setLoading } = useLoading(getProps); const { getLoading, setLoading } = useLoading(getProps);
const { const {
getPaginationInfo, getPaginationInfo,
@ -127,6 +138,7 @@
handleTableChange: onTableChange, handleTableChange: onTableChange,
getDataSourceRef, getDataSourceRef,
getDataSource, getDataSource,
getRawDataSource,
setTableData, setTableData,
updateTableDataRecord, updateTableDataRecord,
findTableDataRecord, findTableDataRecord,
@ -145,7 +157,7 @@
getFieldsValue: formActions.getFieldsValue, getFieldsValue: formActions.getFieldsValue,
clearSelectedRowKeys, clearSelectedRowKeys,
}, },
emit emit,
); );
function handleTableChange(...args) { function handleTableChange(...args) {
@ -170,7 +182,7 @@
tableElRef, tableElRef,
getColumnsRef, getColumnsRef,
getRowSelectionRef, getRowSelectionRef,
getDataSourceRef getDataSourceRef,
); );
const { customRow } = useCustomRow(getProps, { const { customRow } = useCustomRow(getProps, {
@ -199,7 +211,7 @@
getProps, getProps,
getScrollRef, getScrollRef,
tableElRef, tableElRef,
getDataSourceRef getDataSourceRef,
); );
const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } = const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } =
@ -273,6 +285,7 @@
setColumns, setColumns,
setLoading, setLoading,
getDataSource, getDataSource,
getRawDataSource,
setProps, setProps,
getRowSelection, getRowSelection,
getPaginationRef: getPagination, getPaginationRef: getPagination,
@ -307,7 +320,7 @@
wrapRef, wrapRef,
tableAction, tableAction,
redoHeight, redoHeight,
getFormProps, getFormProps: getFormProps as any,
replaceFormSlotKey, replaceFormSlotKey,
getFormSlotKeys, getFormSlotKeys,
getWrapperClass, getWrapperClass,
@ -378,9 +391,9 @@
align-items: center; align-items: center;
} }
.ant-table-tbody > tr.ant-table-row-selected td { //.ant-table-tbody > tr.ant-table-row-selected td {
background-color: fade(@primary-color, 8%) !important; //background-color: fade(@primary-color, 8%) !important;
} //}
} }
.ant-pagination { .ant-pagination {
@ -400,7 +413,7 @@
.ant-table-body { .ant-table-body {
overflow-x: hidden !important; overflow-x: hidden !important;
overflow-y: scroll !important; // overflow-y: scroll !important;
} }
td { td {

View File

@ -95,7 +95,7 @@
.map((action) => { .map((action) => {
const { popConfirm } = action; const { popConfirm } = action;
return { return {
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body, getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
type: 'link', type: 'link',
size: 'small', size: 'small',
...action, ...action,
@ -107,7 +107,7 @@
}); });
}); });
const getDropdownList = computed(() => { const getDropdownList = computed((): any[] => {
return (toRaw(props.dropDownActions) || []) return (toRaw(props.dropDownActions) || [])
.filter((action) => { .filter((action) => {
return hasPermission(action.auth) && isIfShow(action); return hasPermission(action.auth) && isIfShow(action);
@ -133,7 +133,7 @@
function getTooltip(data: string | TooltipProps): TooltipProps { function getTooltip(data: string | TooltipProps): TooltipProps {
return { return {
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body, getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
placement: 'bottom', placement: 'bottom',
...(isString(data) ? { title: data } : data), ...(isString(data) ? { title: data } : data),
}; };

View File

@ -24,7 +24,7 @@
<template v-for="(img, index) in imgList" :key="img"> <template v-for="(img, index) in imgList" :key="img">
<Image <Image
:width="size" :width="size"
:style="{ 'margin-left': index === 0 ? 0 : margin }" :style="{ marginLeft: index === 0 ? 0 : margin }"
:src="srcPrefix + img" :src="srcPrefix + img"
/> />
</template> </template>

View File

@ -21,7 +21,7 @@ export const CellComponent: FunctionalComponent = (
popoverVisible, popoverVisible,
getPopupContainer, getPopupContainer,
}: ComponentProps, }: ComponentProps,
{ attrs } { attrs },
) => { ) => {
const Comp = componentMap.get(component) as typeof defineComponent; const Comp = componentMap.get(component) as typeof defineComponent;
@ -39,6 +39,6 @@ export const CellComponent: FunctionalComponent = (
{ {
default: () => DefaultComp, default: () => DefaultComp,
content: () => ruleMessage, content: () => ruleMessage,
} },
); );
}; };

View File

@ -5,41 +5,41 @@
:class="{ [`${prefixCls}__normal`]: true, 'ellipsis-cell': column.ellipsis }" :class="{ [`${prefixCls}__normal`]: true, 'ellipsis-cell': column.ellipsis }"
@click="handleEdit" @click="handleEdit"
> >
<div class="cell-content" :title="column.ellipsis ? getValues || '' : ''">{{ <div class="cell-content" :title="column.ellipsis ? getValues ?? '' : ''">
getValues || '&nbsp;' {{ getValues ? getValues : '&nbsp;' }}
}}</div> </div>
<FormOutlined :class="`${prefixCls}__normal-icon`" v-if="!column.editRow" /> <FormOutlined :class="`${prefixCls}__normal-icon`" v-if="!column.editRow" />
</div> </div>
<div v-if="isEdit" :class="`${prefixCls}__wrapper`" v-click-outside="onClickOutside"> <a-spin v-if="isEdit" :spinning="spinning">
<CellComponent <div :class="`${prefixCls}__wrapper`" v-click-outside="onClickOutside">
v-bind="getComponentProps" <CellComponent
:component="getComponent" v-bind="getComponentProps"
:style="getWrapperStyle" :component="getComponent"
:popoverVisible="getRuleVisible" :style="getWrapperStyle"
:rule="getRule" :popoverVisible="getRuleVisible"
:ruleMessage="ruleMessage" :rule="getRule"
:class="getWrapperClass" :ruleMessage="ruleMessage"
size="small" :class="getWrapperClass"
ref="elRef" ref="elRef"
@change="handleChange" @change="handleChange"
@options-change="handleOptionsChange" @options-change="handleOptionsChange"
@pressEnter="handleEnter" @pressEnter="handleEnter"
/> />
<div :class="`${prefixCls}__action`" v-if="!getRowEditable"> <div :class="`${prefixCls}__action`" v-if="!getRowEditable">
<CheckOutlined :class="[`${prefixCls}__icon`, 'mx-2']" @click="handleSubmit" /> <CheckOutlined :class="[`${prefixCls}__icon`, 'mx-2']" @click="handleSubmitClick" />
<CloseOutlined :class="`${prefixCls}__icon `" @click="handleCancel" /> <CloseOutlined :class="`${prefixCls}__icon `" @click="handleCancel" />
</div>
</div> </div>
</div> </a-spin>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import type { CSSProperties, PropType } from 'vue'; import type { CSSProperties, PropType } from 'vue';
import { computed, defineComponent, nextTick, ref, toRaw, unref, watchEffect } from 'vue';
import type { BasicColumn } from '../../types/table'; import type { BasicColumn } from '../../types/table';
import type { EditRecordRow } from './index'; import type { EditRecordRow } from './index';
import { CheckOutlined, CloseOutlined, FormOutlined } from '@ant-design/icons-vue';
import { defineComponent, ref, unref, nextTick, computed, watchEffect, toRaw } from 'vue';
import { FormOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
import { CellComponent } from './CellComponent'; import { CellComponent } from './CellComponent';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
@ -48,14 +48,15 @@
import clickOutside from '/@/directives/clickOutside'; import clickOutside from '/@/directives/clickOutside';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { isString, isBoolean, isFunction, isNumber, isArray } from '/@/utils/is'; import { isArray, isBoolean, isFunction, isNumber, isString } from '/@/utils/is';
import { createPlaceholderMessage } from './helper'; import { createPlaceholderMessage } from './helper';
import { set, omit } from 'lodash-es'; import { omit, pick, set } from 'lodash-es';
import { treeToList } from '/@/utils/helper/treeHelper'; import { treeToList } from '/@/utils/helper/treeHelper';
import { Spin } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'EditableCell', name: 'EditableCell',
components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent }, components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent, ASpin: Spin },
directives: { directives: {
clickOutside, clickOutside,
}, },
@ -82,6 +83,7 @@
const optionsRef = ref<LabelValueOptions>([]); const optionsRef = ref<LabelValueOptions>([]);
const currentValueRef = ref<any>(props.value); const currentValueRef = ref<any>(props.value);
const defaultValueRef = ref<any>(props.value); const defaultValueRef = ref<any>(props.value);
const spinning = ref<boolean>(false);
const { prefixCls } = useDesign('editable-cell'); const { prefixCls } = useDesign('editable-cell');
@ -113,6 +115,7 @@
const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val; const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val;
return { return {
size: 'small',
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body, getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
getCalendarContainer: () => unref(table?.wrapRef.value) ?? document.body, getCalendarContainer: () => unref(table?.wrapRef.value) ?? document.body,
placeholder: createPlaceholderMessage(unref(getComponent)), placeholder: createPlaceholderMessage(unref(getComponent)),
@ -214,8 +217,7 @@
if (isBoolean(editRule) && !currentValue && !isNumber(currentValue)) { if (isBoolean(editRule) && !currentValue && !isNumber(currentValue)) {
ruleVisible.value = true; ruleVisible.value = true;
const component = unref(getComponent); const component = unref(getComponent);
const message = createPlaceholderMessage(component); ruleMessage.value = createPlaceholderMessage(component);
ruleMessage.value = message;
return false; return false;
} }
if (isFunction(editRule)) { if (isFunction(editRule)) {
@ -248,6 +250,35 @@
const dataKey = (dataIndex || key) as string; const dataKey = (dataIndex || key) as string;
if (!record.editable) {
const { getBindValues } = table;
const { beforeEditSubmit, columns } = unref(getBindValues);
if (beforeEditSubmit && isFunction(beforeEditSubmit)) {
spinning.value = true;
const keys: string[] = columns
.map((_column) => _column.dataIndex)
.filter((field) => !!field) as string[];
let result: any = true;
try {
result = await beforeEditSubmit({
record: pick(record, keys),
index,
key,
value,
});
} catch (e) {
result = false;
} finally {
spinning.value = false;
}
if (result === false) {
return;
}
}
}
set(record, dataKey, value); set(record, dataKey, value);
//const record = await table.updateTableData(index, dataKey, value); //const record = await table.updateTableData(index, dataKey, value);
needEmit && table.emit?.('edit-end', { record, index, key, value }); needEmit && table.emit?.('edit-end', { record, index, key, value });
@ -261,6 +292,10 @@
handleSubmit(); handleSubmit();
} }
function handleSubmitClick() {
handleSubmit();
}
function handleCancel() { function handleCancel() {
isEdit.value = false; isEdit.value = false;
currentValueRef.value = defaultValueRef.value; currentValueRef.value = defaultValueRef.value;
@ -365,7 +400,8 @@
getRowEditable, getRowEditable,
getValues, getValues,
handleEnter, handleEnter,
// getSize, handleSubmitClick,
spinning,
}; };
}, },
}); });

View File

@ -282,7 +282,7 @@
nextTick(() => { nextTick(() => {
const columnListEl = unref(columnListRef); const columnListEl = unref(columnListRef);
if (!columnListEl) return; if (!columnListEl) return;
const el = columnListEl.$el; const el = columnListEl.$el as any;
if (!el) return; if (!el) return;
// Drag and drop sort // Drag and drop sort
const { initSortable } = useSortable(el, { const { initSortable } = useSortable(el, {
@ -351,7 +351,7 @@
const visible = const visible =
columns.findIndex( columns.findIndex(
(c: BasicColumn | string) => (c: BasicColumn | string) =>
c === col.value || (typeof c !== 'string' && c.dataIndex === col.value) c === col.value || (typeof c !== 'string' && c.dataIndex === col.value),
) !== -1; ) !== -1;
return { dataIndex: col.value, fixed: col.fixed, visible }; return { dataIndex: col.value, fixed: col.fixed, visible };
}); });

View File

@ -40,7 +40,7 @@ function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean)
function handleIndexColumn( function handleIndexColumn(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
getPaginationRef: ComputedRef<boolean | PaginationProps>, getPaginationRef: ComputedRef<boolean | PaginationProps>,
columns: BasicColumn[] columns: BasicColumn[],
) { ) {
const { t } = useI18n(); const { t } = useI18n();
@ -102,7 +102,7 @@ function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: Bas
export function useColumns( export function useColumns(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
getPaginationRef: ComputedRef<boolean | PaginationProps> getPaginationRef: ComputedRef<boolean | PaginationProps>,
) { ) {
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>; const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
let cacheColumns = unref(propsRef).columns; let cacheColumns = unref(propsRef).columns;
@ -122,7 +122,7 @@ export function useColumns(
handleItem( handleItem(
item, item,
Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots,
); );
}); });
return columns; return columns;
@ -179,7 +179,7 @@ export function useColumns(
(columns) => { (columns) => {
columnsRef.value = columns; columnsRef.value = columns;
cacheColumns = columns?.filter((item) => !item.flag) ?? []; cacheColumns = columns?.filter((item) => !item.flag) ?? [];
} },
); );
function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) { function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
@ -288,7 +288,7 @@ function sortFixedColumn(columns: BasicColumn[]) {
defColumns.push(column); defColumns.push(column);
} }
return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter( return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter(
(item) => !item.defaultHidden (item) => !item.defaultHidden,
); );
} }

View File

@ -15,7 +15,7 @@ interface Options {
function getKey( function getKey(
record: Recordable, record: Recordable,
rowKey: string | ((record: Record<string, any>) => string) | undefined, rowKey: string | ((record: Record<string, any>) => string) | undefined,
autoCreateKey?: boolean autoCreateKey?: boolean,
) { ) {
if (!rowKey || autoCreateKey) { if (!rowKey || autoCreateKey) {
return record[ROW_KEY]; return record[ROW_KEY];
@ -31,7 +31,7 @@ function getKey(
export function useCustomRow( export function useCustomRow(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
{ setSelectedRowKeys, getSelectRowKeys, getAutoCreateKey, clearSelectedRowKeys, emit }: Options { setSelectedRowKeys, getSelectRowKeys, getAutoCreateKey, clearSelectedRowKeys, emit }: Options,
) { ) {
const customRow = (record: Recordable, index: number) => { const customRow = (record: Recordable, index: number) => {
return { return {

View File

@ -40,13 +40,14 @@ export function useDataSource(
clearSelectedRowKeys, clearSelectedRowKeys,
tableData, tableData,
}: ActionType, }: ActionType,
emit: EmitType emit: EmitType,
) { ) {
const searchState = reactive<SearchState>({ const searchState = reactive<SearchState>({
sortInfo: {}, sortInfo: {},
filterInfo: {}, filterInfo: {},
}); });
const dataSourceRef = ref<Recordable[]>([]); const dataSourceRef = ref<Recordable[]>([]);
const rawDataSourceRef = ref<Recordable>({});
watchEffect(() => { watchEffect(() => {
tableData.value = unref(dataSourceRef); tableData.value = unref(dataSourceRef);
@ -60,13 +61,13 @@ export function useDataSource(
}, },
{ {
immediate: true, immediate: true,
} },
); );
function handleTableChange( function handleTableChange(
pagination: PaginationProps, pagination: PaginationProps,
filters: Partial<Recordable<string[]>>, filters: Partial<Recordable<string[]>>,
sorter: SorterResult sorter: SorterResult,
) { ) {
const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef); const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef);
if (clearSelectOnPageChange) { if (clearSelectOnPageChange) {
@ -147,7 +148,7 @@ export function useDataSource(
function updateTableDataRecord( function updateTableDataRecord(
rowKey: string | number, rowKey: string | number,
record: Recordable record: Recordable,
): Recordable | undefined { ): Recordable | undefined {
const row = findTableDataRecord(rowKey); const row = findTableDataRecord(rowKey);
@ -205,7 +206,7 @@ export function useDataSource(
const { pageField, sizeField, listField, totalField } = Object.assign( const { pageField, sizeField, listField, totalField } = Object.assign(
{}, {},
FETCH_SETTING, FETCH_SETTING,
fetchSetting fetchSetting,
); );
let pageParams: Recordable = {}; let pageParams: Recordable = {};
@ -235,6 +236,7 @@ export function useDataSource(
} }
const res = await api(params); const res = await api(params);
rawDataSourceRef.value = res;
const isArrayResult = Array.isArray(res); const isArrayResult = Array.isArray(res);
@ -287,6 +289,10 @@ export function useDataSource(
return getDataSourceRef.value as T[]; return getDataSourceRef.value as T[];
} }
function getRawDataSource<T = Recordable>() {
return rawDataSourceRef.value as T;
}
async function reload(opt?: FetchParams) { async function reload(opt?: FetchParams) {
await fetch(opt); await fetch(opt);
} }
@ -300,6 +306,7 @@ export function useDataSource(
return { return {
getDataSourceRef, getDataSourceRef,
getDataSource, getDataSource,
getRawDataSource,
getRowKey, getRowKey,
setTableData, setTableData,
getAutoCreateKey, getAutoCreateKey,

View File

@ -8,7 +8,7 @@ export function useLoading(props: ComputedRef<BasicTableProps>) {
() => unref(props).loading, () => unref(props).loading,
(loading) => { (loading) => {
loadingRef.value = loading; loadingRef.value = loading;
} },
); );
const getLoading = computed(() => unref(loadingRef)); const getLoading = computed(() => unref(loadingRef));

View File

@ -8,7 +8,7 @@ import { findNodeAll } from '/@/utils/helper/treeHelper';
export function useRowSelection( export function useRowSelection(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
tableData: Ref<Recordable[]>, tableData: Ref<Recordable[]>,
emit: EmitType emit: EmitType,
) { ) {
const selectedRowKeysRef = ref<string[]>([]); const selectedRowKeysRef = ref<string[]>([]);
const selectedRowRef = ref<Recordable[]>([]); const selectedRowRef = ref<Recordable[]>([]);
@ -35,7 +35,7 @@ export function useRowSelection(
() => unref(propsRef).rowSelection?.selectedRowKeys, () => unref(propsRef).rowSelection?.selectedRowKeys,
(v: string[]) => { (v: string[]) => {
setSelectedRowKeys(v); setSelectedRowKeys(v);
} },
); );
watch( watch(
@ -52,7 +52,8 @@ export function useRowSelection(
rows: getSelectRows(), rows: getSelectRows(),
}); });
}); });
} },
{ deep: true },
); );
const getAutoCreateKey = computed(() => { const getAutoCreateKey = computed(() => {
@ -66,13 +67,19 @@ export function useRowSelection(
function setSelectedRowKeys(rowKeys: string[]) { function setSelectedRowKeys(rowKeys: string[]) {
selectedRowKeysRef.value = rowKeys; selectedRowKeysRef.value = rowKeys;
selectedRowRef.value = findNodeAll( const allSelectedRows = findNodeAll(
toRaw(unref(tableData)), toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))),
(item) => rowKeys.includes(item[unref(getRowKey) as string]), (item) => rowKeys.includes(item[unref(getRowKey) as string]),
{ {
children: propsRef.value.childrenColumnName ?? 'children', children: propsRef.value.childrenColumnName ?? 'children',
} },
); );
const trueSelectedRows: any[] = [];
rowKeys.forEach((key: string) => {
const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key);
found && trueSelectedRows.push(found);
});
selectedRowRef.value = trueSelectedRows;
} }
function setSelectedRows(rows: Recordable[]) { function setSelectedRows(rows: Recordable[]) {

View File

@ -18,7 +18,7 @@ export function useTable(tableProps?: Props): [
(instance: TableActionType, formInstance: UseTableMethod) => void, (instance: TableActionType, formInstance: UseTableMethod) => void,
TableActionType & { TableActionType & {
getForm: () => FormActionType; getForm: () => FormActionType;
} },
] { ] {
const tableRef = ref<Nullable<TableActionType>>(null); const tableRef = ref<Nullable<TableActionType>>(null);
const loadedRef = ref<Nullable<boolean>>(false); const loadedRef = ref<Nullable<boolean>>(false);
@ -50,7 +50,7 @@ export function useTable(tableProps?: Props): [
{ {
immediate: true, immediate: true,
deep: true, deep: true,
} },
); );
} }
@ -58,7 +58,7 @@ export function useTable(tableProps?: Props): [
const table = unref(tableRef); const table = unref(tableRef);
if (!table) { if (!table) {
error( error(
'The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!' 'The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!',
); );
} }
return table as TableActionType; return table as TableActionType;
@ -82,6 +82,9 @@ export function useTable(tableProps?: Props): [
getDataSource: () => { getDataSource: () => {
return getTableInstance().getDataSource(); return getTableInstance().getDataSource();
}, },
getRawDataSource: () => {
return getTableInstance().getRawDataSource();
},
getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => { getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => {
const columns = getTableInstance().getColumns({ ignoreIndex }) || []; const columns = getTableInstance().getColumns({ ignoreIndex }) || [];
return toRaw(columns); return toRaw(columns);

View File

@ -6,7 +6,7 @@ import { ROW_KEY } from '../const';
export function useTableExpand( export function useTableExpand(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
tableData: Ref<Recordable[]>, tableData: Ref<Recordable[]>,
emit: EmitType emit: EmitType,
) { ) {
const expandedRowKeys = ref<string[]>([]); const expandedRowKeys = ref<string[]>([]);

View File

@ -12,7 +12,7 @@ export function useTableFooter(
scrollToFirstRowOnChange: boolean; scrollToFirstRowOnChange: boolean;
}>, }>,
tableElRef: Ref<ComponentRef>, tableElRef: Ref<ComponentRef>,
getDataSourceRef: ComputedRef<Recordable> getDataSourceRef: ComputedRef<Recordable>,
) { ) {
const getIsEmptyData = computed(() => { const getIsEmptyData = computed(() => {
return (unref(getDataSourceRef) || []).length === 0; return (unref(getDataSourceRef) || []).length === 0;
@ -43,7 +43,7 @@ export function useTableFooter(
name: 'scroll', name: 'scroll',
listener: () => { listener: () => {
const footerBodyDom = tableEl.$el.querySelector( const footerBodyDom = tableEl.$el.querySelector(
'.ant-table-footer .ant-table-body' '.ant-table-footer .ant-table-body',
) as HTMLDivElement; ) as HTMLDivElement;
if (!footerBodyDom || !bodyDom) return; if (!footerBodyDom || !bodyDom) return;
footerBodyDom.scrollLeft = bodyDom.scrollLeft; footerBodyDom.scrollLeft = bodyDom.scrollLeft;

View File

@ -8,7 +8,7 @@ export function useTableForm(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
slots: Slots, slots: Slots,
fetch: (opt?: FetchParams | undefined) => Promise<void>, fetch: (opt?: FetchParams | undefined) => Promise<void>,
getLoading: ComputedRef<boolean | undefined> getLoading: ComputedRef<boolean | undefined>,
) { ) {
const getFormProps = computed((): Partial<FormProps> => { const getFormProps = computed((): Partial<FormProps> => {
const { formConfig } = unref(propsRef); const { formConfig } = unref(propsRef);
@ -21,9 +21,11 @@ export function useTableForm(
}; };
}); });
const getFormSlotKeys = computed(() => { const getFormSlotKeys: ComputedRef<string[]> = computed(() => {
const keys = Object.keys(slots); const keys = Object.keys(slots);
return keys.map((item) => (item.startsWith('form-') ? item : null)).filter(Boolean); return keys
.map((item) => (item.startsWith('form-') ? item : null))
.filter((item) => !!item) as string[];
}); });
function replaceFormSlotKey(key: string) { function replaceFormSlotKey(key: string) {

Some files were not shown because too many files have changed in this diff Show More