mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-25 16:16:20 +08:00
Compare commits
92 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
038936ff7d | ||
![]() |
960f1d3c0b | ||
![]() |
f67b5d8569 | ||
![]() |
f99cc9b9fe | ||
![]() |
0cf2271667 | ||
![]() |
6d2de002ef | ||
![]() |
617e594d8d | ||
![]() |
4aac1c388c | ||
![]() |
7b6531a309 | ||
![]() |
65651fc25c | ||
![]() |
4fcbdd3925 | ||
![]() |
db2a27060c | ||
![]() |
d9bfe96dad | ||
![]() |
77a0ad450d | ||
![]() |
c37ed8f7e9 | ||
![]() |
1698be7ce4 | ||
![]() |
ea5c66b6eb | ||
![]() |
371c972cc1 | ||
![]() |
2880174be2 | ||
![]() |
b0c0b916fd | ||
![]() |
f314826230 | ||
![]() |
56c5dce99f | ||
![]() |
95abe06107 | ||
![]() |
ecfe66a019 | ||
![]() |
25699c0b60 | ||
![]() |
5b7b6b1780 | ||
![]() |
57ff038d82 | ||
![]() |
baf406e7e2 | ||
![]() |
1745f480fd | ||
![]() |
cec5c11289 | ||
![]() |
dd1b16acdc | ||
![]() |
64a4992a84 | ||
![]() |
cae5538aba | ||
![]() |
e7868e7193 | ||
![]() |
71c4edad63 | ||
![]() |
65fba1c329 | ||
![]() |
8d3981f599 | ||
![]() |
cca7f59fac | ||
![]() |
1a5692060b | ||
![]() |
4974de2553 | ||
![]() |
f83002441d | ||
![]() |
e84c4051f3 | ||
![]() |
af39afa24b | ||
![]() |
2dcd733e16 | ||
![]() |
d5fed8a47c | ||
![]() |
a6086f4cc8 | ||
![]() |
d9cdf3f034 | ||
![]() |
0bc01d8528 | ||
![]() |
5d36b1a560 | ||
![]() |
c89417f523 | ||
![]() |
dcba0ca837 | ||
![]() |
e69dd1e223 | ||
![]() |
fee808198e | ||
![]() |
cfdb09fe5b | ||
![]() |
821238ea04 | ||
![]() |
bcd98ee067 | ||
![]() |
144cdd4680 | ||
![]() |
1fee161786 | ||
![]() |
265627fcc8 | ||
![]() |
223562eab5 | ||
![]() |
22052f10f9 | ||
![]() |
478802b426 | ||
![]() |
5a2d74249e | ||
![]() |
0ee721183b | ||
![]() |
b66a0def98 | ||
![]() |
679a23332f | ||
![]() |
7538c57db7 | ||
![]() |
88e77dbf99 | ||
![]() |
4348d21da8 | ||
![]() |
d7783baad4 | ||
![]() |
2af93c9f53 | ||
![]() |
ef5285385f | ||
![]() |
ba5b8f8506 | ||
![]() |
08a1f7b682 | ||
![]() |
06018add79 | ||
![]() |
29ef0d3915 | ||
![]() |
17f5b1b210 | ||
![]() |
338d077ab3 | ||
![]() |
641d0b38ba | ||
![]() |
fa4bfc4d50 | ||
![]() |
7ae2ec03a7 | ||
![]() |
2f655c2127 | ||
![]() |
1da97c3ff8 | ||
![]() |
69a6e9023e | ||
![]() |
504cf725f1 | ||
![]() |
3623ea7f7b | ||
![]() |
49c4dc646a | ||
![]() |
0ffd777e54 | ||
![]() |
f5cd3ad593 | ||
![]() |
4e8ac0ec4c | ||
![]() |
d53a5b22cc | ||
![]() |
9c027fdcf5 |
@@ -11,13 +11,13 @@ VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
VITE_GLOB_API_URL = /basic-api
|
||||
|
||||
# File upload address, optional
|
||||
# It can be forwarded by nginx or write the actual address directly
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
VITE_GLOB_UPLOAD_URL = /upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
VITE_GLOB_API_URL_PREFIX =
|
||||
|
||||
VITE_ENABLE_ANALYZE = true
|
||||
|
@@ -5,10 +5,10 @@ VITE_USE_MOCK = true
|
||||
VITE_PUBLIC_PATH = /
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
VITE_GLOB_API_URL = /basic-api
|
||||
|
||||
# File upload address, optional
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
VITE_GLOB_UPLOAD_URL = /upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
VITE_GLOB_API_URL_PREFIX =
|
||||
|
@@ -13,10 +13,10 @@ VITE_DROP_CONSOLE = true
|
||||
# Optional: gzip | brotli | none
|
||||
# If you need multiple forms, you can use `,` to separate
|
||||
VITE_BUILD_COMPRESS = 'none'
|
||||
VITE_GLOB_API_URL="__vg_base_url"
|
||||
VITE_GLOB_API_URL = "__vg_base_url"
|
||||
|
||||
# File upload address, optional
|
||||
# It can be forwarded by nginx or write the actual address directly
|
||||
VITE_GLOB_UPLOAD_URL=/files/upload
|
||||
VITE_GLOB_UPLOAD_URL = /files/upload
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
VITE_GLOB_API_URL_PREFIX =
|
||||
|
@@ -11,11 +11,11 @@ VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
VITE_GLOB_API_URL = /basic-api
|
||||
|
||||
# File upload address, optional
|
||||
# It can be forwarded by nginx or write the actual address directly
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
VITE_GLOB_UPLOAD_URL = /upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
VITE_GLOB_API_URL_PREFIX =
|
||||
|
@@ -1,4 +1,4 @@
|
||||
NODE_ENV=production
|
||||
NODE_ENV = production
|
||||
# Whether to open mock
|
||||
VITE_USE_MOCK = true
|
||||
|
||||
@@ -11,11 +11,11 @@ VITE_PUBLIC_PATH = /
|
||||
VITE_BUILD_COMPRESS = 'none'
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/basic-api
|
||||
VITE_GLOB_API_URL = /basic-api
|
||||
|
||||
# File upload address, optional
|
||||
# It can be forwarded by nginx or write the actual address directly
|
||||
VITE_GLOB_UPLOAD_URL=/upload
|
||||
VITE_GLOB_UPLOAD_URL = /upload
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
VITE_GLOB_API_URL_PREFIX =
|
||||
|
2
.github/ISSUE_TEMPLATE/1-bug.md
vendored
2
.github/ISSUE_TEMPLATE/1-bug.md
vendored
@@ -36,4 +36,4 @@ Please describe the steps of the problem in detail to ensure that we can restore
|
||||
|
||||
- Operating System:
|
||||
- Node version:
|
||||
- Package manager (npm/yarn/pnpm) and version:
|
||||
- pnpm version:
|
||||
|
2
.github/ISSUE_TEMPLATE/3-bug-cn.md
vendored
2
.github/ISSUE_TEMPLATE/3-bug-cn.md
vendored
@@ -25,4 +25,4 @@ assignees: ''
|
||||
|
||||
- 操作系统:
|
||||
- Node 版本:
|
||||
- 包管理器 (npm/yarn/pnpm) 及其版本:
|
||||
- pnpm 版本:
|
||||
|
24
.github/workflows/deploy.yml
vendored
24
.github/workflows/deploy.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# - uses: NullVoxPopuli/action-setup-pnpm@v2
|
||||
# - uses: NullVoxPopuli/action-setup-pnpm@v2
|
||||
|
||||
- name: Sed Config Base
|
||||
shell: bash
|
||||
@@ -80,17 +80,17 @@ jobs:
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
# - name: Get yarn cache directory path
|
||||
# id: yarn-cache-dir-path
|
||||
# run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Cache dependencies
|
||||
# uses: actions/cache@v3
|
||||
# with:
|
||||
# path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
# key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-yarn-
|
||||
# - name: Get yarn cache directory path
|
||||
# id: yarn-cache-dir-path
|
||||
# run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Cache dependencies
|
||||
# uses: actions/cache@v3
|
||||
# with:
|
||||
# path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
# key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-yarn-
|
||||
|
||||
- name: Set SSH Environment
|
||||
env:
|
||||
|
22
.github/workflows/release-tag.yml
vendored
Normal file
22
.github/workflows/release-tag.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Create Release Tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create Release for Tag
|
||||
id: release_tag
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
generateReleaseNotes: 'true'
|
||||
body: |
|
||||
> Please refer to [CHANGELOG.md](https://github.com/anncwb/vue-vben-admin/blob/main/CHANGELOG.md) for details.
|
24
.github/workflows/release.yml
vendored
24
.github/workflows/release.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Create Release for Tag
|
||||
id: release_tag
|
||||
uses: yyx990803/release-tag@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.OPER_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
body: |
|
||||
Please refer to [CHANGELOG.md](https://github.com/anncwb/vue-vben-admin/blob/main/CHANGELOG.md) for details.
|
20
.github/workflows/stale.yml
vendored
20
.github/workflows/stale.yml
vendored
@@ -1,18 +1,18 @@
|
||||
name: "Close stale issues"
|
||||
name: 'Close stale issues'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.OPER_TOKEN }}
|
||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
||||
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
||||
exempt-issue-labels: 'bug,enhancement'
|
||||
days-before-stale: 60
|
||||
days-before-close: 7
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.OPER_TOKEN }}
|
||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
||||
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
||||
exempt-issue-labels: 'bug,enhancement'
|
||||
days-before-stale: 60
|
||||
days-before-close: 7
|
||||
|
@@ -5,4 +5,4 @@
|
||||
|
||||
PATH="/usr/local/bin:$PATH"
|
||||
|
||||
npx --no-install commitlint --edit "$1"
|
||||
# npx --no-install commitlint --edit "$1"
|
||||
|
@@ -7,4 +7,4 @@
|
||||
PATH="/usr/local/bin:$PATH"
|
||||
|
||||
# Format and submit code according to lintstagedrc.js configuration
|
||||
pnpm exec lint-staged
|
||||
# pnpm exec lint-staged
|
||||
|
1
.npmrc
1
.npmrc
@@ -5,3 +5,4 @@ public-hoist-pattern[]=lint-staged
|
||||
public-hoist-pattern[]=*stylelint*
|
||||
public-hoist-pattern[]=@commitlint/cli
|
||||
public-hoist-pattern[]=@vben/eslint-config
|
||||
package-manager-strict=false
|
||||
|
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
@@ -9,6 +9,6 @@
|
||||
"antfu.iconify",
|
||||
"antfu.unocss",
|
||||
"mikestead.dotenv",
|
||||
"warmthsea.vscode-custom-code-color",
|
||||
"warmthsea.vscode-custom-code-color"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -10,4 +10,4 @@
|
||||
"sourceMaps": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
28
.vscode/settings.json
vendored
28
.vscode/settings.json
vendored
@@ -55,14 +55,7 @@
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
"stylelint.enable": true,
|
||||
"stylelint.validate": [
|
||||
"css",
|
||||
"less",
|
||||
"postcss",
|
||||
"scss",
|
||||
"vue",
|
||||
"sass"
|
||||
],
|
||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
|
||||
"path-intellisense.mappings": {
|
||||
"@/": "${workspaceRoot}/src"
|
||||
},
|
||||
@@ -101,24 +94,15 @@
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"i18n-ally.localesPaths": [
|
||||
"src/locales/lang"
|
||||
],
|
||||
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||
"i18n-ally.enabledParsers": [
|
||||
"json",
|
||||
"ts",
|
||||
"js"
|
||||
],
|
||||
"i18n-ally.enabledParsers": ["json", "ts", "js"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": [
|
||||
"vue",
|
||||
"react"
|
||||
],
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
"cSpell.words": [
|
||||
"antd",
|
||||
"antv",
|
||||
@@ -188,5 +172,5 @@
|
||||
"terminal.integrated.scrollback": 10000,
|
||||
"nuxt.isNuxtApp": false,
|
||||
"vscodeCustomCodeColor.highlightValue": "v-auth",
|
||||
"vscodeCustomCodeColor.highlightValueColor": "#6366f1",
|
||||
}
|
||||
"vscodeCustomCodeColor.highlightValueColor": "#6366f1"
|
||||
}
|
||||
|
@@ -308,7 +308,7 @@
|
||||
- Fix the height issue of the lock screen pop-up window
|
||||
- Fixed the problem that the half-selected state of the `Column Display` checkbox of `BaiscTable` was incorrectly displayed
|
||||
- Fixed the problem that the preview list of the `BasicUpload` component could not be displayed in some cases
|
||||
- Fix the problem that the `options` setting of ` RadioButtonGroup``disabled ` does not take effect
|
||||
- Fix the problem that the `options` setting of `RadioButtonGroup``disabled` does not take effect
|
||||
- Fix the problem that the button for uploading pictures in the read-only mode of the `Tinymce` component is still available
|
||||
- Fix the stuttering problem of `BasicForm` under certain circumstances
|
||||
- Fix the problem that "directory" routing does not work
|
||||
|
66
CHANGELOG.md
66
CHANGELOG.md
@@ -1,3 +1,69 @@
|
||||
## [2.11.5](https://github.com/vbenjs/vue-vben-admin/compare/v2.11.4...v2.11.5) (2024-05-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- 路由参数存在非英文字符的情况下 会生成一个新的tab 而非返回原有tab ([#3832](https://github.com/vbenjs/vue-vben-admin/issues/3832)) ([1fee161](https://github.com/vbenjs/vue-vben-admin/commit/1fee161786fee79a06fb3b308374db098abd461a))
|
||||
- 修复表单重置后,页面变化了,但是由于异步问题导致表单内部的状态没有及时同步 ([#3882](https://github.com/vbenjs/vue-vben-admin/issues/3882)) ([5d36b1a](https://github.com/vbenjs/vue-vben-admin/commit/5d36b1a5604f72921bf09c16a78e5e287a1ba9d0))
|
||||
- **Application:** search menu now correctly lowercases input keys ([#3842](https://github.com/vbenjs/vue-vben-admin/issues/3842)) ([144cdd4](https://github.com/vbenjs/vue-vben-admin/commit/144cdd468092f9314abf766ffc2eccc66c00f08a))
|
||||
- **BasicForm:** 修复FormSchema中使用ifShow隐藏字段时,默认表单查询重置按钮位置偏移量计算问题 ([#3830](https://github.com/vbenjs/vue-vben-admin/issues/3830)) ([478802b](https://github.com/vbenjs/vue-vben-admin/commit/478802b42625f74e8e8f817dea343b0692e3d024))
|
||||
- **BasicForm:** setFieldsValue not work in form when use date comp ([#3819](https://github.com/vbenjs/vue-vben-admin/issues/3819)) ([7538c57](https://github.com/vbenjs/vue-vben-admin/commit/7538c57db755f221d201e3fdb5052ecf1f42fd9a))
|
||||
- **BasicForm:** when value is 0 or false resetFields is not work ([#3828](https://github.com/vbenjs/vue-vben-admin/issues/3828)) ([22052f1](https://github.com/vbenjs/vue-vben-admin/commit/22052f10f9264008dcd25f6efdd53d679585407a))
|
||||
- **Breadcrumb:** if hideBreadcrumb is true and hidden ([#3821](https://github.com/vbenjs/vue-vben-admin/issues/3821)) ([b66a0de](https://github.com/vbenjs/vue-vben-admin/commit/b66a0def98018fc1504573692a9b7a83b5c2d483))
|
||||
- **imgUpload:** disabled not effect in the form ([#3809](https://github.com/vbenjs/vue-vben-admin/issues/3809)) ([4348d21](https://github.com/vbenjs/vue-vben-admin/commit/4348d21da80a1e54c94fb9528617b29090701080))
|
||||
- **Loading:** 处理v-loading指令和useLoading的内存泄露 ([#3861](https://github.com/vbenjs/vue-vben-admin/issues/3861)) ([bcd98ee](https://github.com/vbenjs/vue-vben-admin/commit/bcd98ee0672047aafebdd504ef0ecc630b5068da))
|
||||
- **loading:** useLoading is not working as expected ([#3877](https://github.com/vbenjs/vue-vben-admin/issues/3877)) ([c89417f](https://github.com/vbenjs/vue-vben-admin/commit/c89417f523bf4c7e2329d943796c3dd92c066d3a))
|
||||
- **useDataSource:** state mutations in computed getters should be avoided ([#3859](https://github.com/vbenjs/vue-vben-admin/issues/3859)) ([fee8081](https://github.com/vbenjs/vue-vben-admin/commit/fee808198e5c2038424a5f5b1da41b11d16d1508))
|
||||
|
||||
### Features
|
||||
|
||||
- add devtools plugin instead of inspector plugin ([#3856](https://github.com/vbenjs/vue-vben-admin/issues/3856)) ([e69dd1e](https://github.com/vbenjs/vue-vben-admin/commit/e69dd1e223a2e817805739f11823092992d14ae1))
|
||||
- **BasicForm:** add prefix slot for schema ([#3840](https://github.com/vbenjs/vue-vben-admin/issues/3840)) ([265627f](https://github.com/vbenjs/vue-vben-admin/commit/265627fcc8a197861aea2f04641f457548180177))
|
||||
- **codeEditor:** add type and config && add use case ([#3829](https://github.com/vbenjs/vue-vben-admin/issues/3829)) ([0ee7211](https://github.com/vbenjs/vue-vben-admin/commit/0ee721183bf52c4d1239a7966cc76f2150b43b13))
|
||||
- **Demo:** add ScreenShot page demo ([#3826](https://github.com/vbenjs/vue-vben-admin/issues/3826)) ([5a2d742](https://github.com/vbenjs/vue-vben-admin/commit/5a2d74249e9e9a9631f3f43e2249b7ccc13f6da4))
|
||||
- **form:** add valueFormat for schema ([#3873](https://github.com/vbenjs/vue-vben-admin/issues/3873)) ([0bc01d8](https://github.com/vbenjs/vue-vben-admin/commit/0bc01d8528fc11904628974799ab44180e3e3314))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- **BasicForm:** fix invaild defaultValue && split-setdefault-setvalue ([#3815](https://github.com/vbenjs/vue-vben-admin/issues/3815)) ([88e77db](https://github.com/vbenjs/vue-vben-admin/commit/88e77dbf994f594bc31189b896deab4be18351b8))
|
||||
- **form->util:** duplicate judge ([#3865](https://github.com/vbenjs/vue-vben-admin/issues/3865)) ([dcba0ca](https://github.com/vbenjs/vue-vben-admin/commit/dcba0ca837a0f72beaa09ff394fa9b6ff465dec1))
|
||||
- **menu->search:** highlight match chars when search menu ([#3880](https://github.com/vbenjs/vue-vben-admin/issues/3880)) ([d5fed8a](https://github.com/vbenjs/vue-vben-admin/commit/d5fed8a47c031f6f228ca41ed29c0f9aaf05f623))
|
||||
|
||||
## [2.11.4](https://github.com/vbenjs/vue-vben-admin/compare/v2.11.3...v2.11.4) (2024-05-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **BasicForm:** 修复 SetFieldsValue 设置值时,会将 Number 类型的值转为 string ([#3802](https://github.com/vbenjs/vue-vben-admin/issues/3802)) ([08a1f7b](https://github.com/vbenjs/vue-vben-admin/commit/08a1f7b682114bdf758ea9dcd4b84daea0d5f196))
|
||||
- **breadcrumb:** if hideChildrenInmenu is true & hidden dropdown-menu ([#3807](https://github.com/vbenjs/vue-vben-admin/issues/3807)) ([2af93c9](https://github.com/vbenjs/vue-vben-admin/commit/2af93c9f5307ffdbb29653303177b2c8631e789a))
|
||||
- **docker:** update node version of dockerfile ([#3788](https://github.com/vbenjs/vue-vben-admin/issues/3788)) ([338d077](https://github.com/vbenjs/vue-vben-admin/commit/338d077ab3669ef116e7406c586fe2cb59952022))
|
||||
- **imgupload:** resultField causing with error display && setField uncertain ([#3798](https://github.com/vbenjs/vue-vben-admin/issues/3798)) ([06018ad](https://github.com/vbenjs/vue-vben-admin/commit/06018add798a6c23ebbfa91a3f4d625c2a57e458))
|
||||
|
||||
### Features
|
||||
|
||||
- **upload->previewColumns:** Adapt functions && chore upload demo ([#3799](https://github.com/vbenjs/vue-vben-admin/issues/3799)) ([29ef0d3](https://github.com/vbenjs/vue-vben-admin/commit/29ef0d39157957146015e1b914c26d2b6d1bf25e))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- **util:** remove handleInputNumberValue ([#3806](https://github.com/vbenjs/vue-vben-admin/issues/3806)) ([ba5b8f8](https://github.com/vbenjs/vue-vben-admin/commit/ba5b8f8506bb9d052ce2705653f255f0401963e8))
|
||||
|
||||
## [2.11.3](https://github.com/vbenjs/vue-vben-admin/compare/v2.11.2...v2.11.3) (2024-04-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **deps:** lock vue version to 3.4.23 ([#3785](https://github.com/vbenjs/vue-vben-admin/issues/3785)) ([2f655c2](https://github.com/vbenjs/vue-vben-admin/commit/2f655c2127753c0cde1cb29834314e961ce0930e)), closes [#3783](https://github.com/vbenjs/vue-vben-admin/issues/3783)
|
||||
- **upload:** disabled prop not effect to upload in the form ([#3780](https://github.com/vbenjs/vue-vben-admin/issues/3780)) ([69a6e90](https://github.com/vbenjs/vue-vben-admin/commit/69a6e9023ef80a5504178d0887119f8e7bbd5113))
|
||||
|
||||
### Features
|
||||
|
||||
- **BasicForm->Components:** add beforeFetch & afterFetch to apicomp && perf the code ([#3786](https://github.com/vbenjs/vue-vben-admin/issues/3786)) ([7ae2ec0](https://github.com/vbenjs/vue-vben-admin/commit/7ae2ec03a773c2223feabbd1e341e90f012f8b7e))
|
||||
- **demo:** use Tour component replace dirverjs ([#3777](https://github.com/vbenjs/vue-vben-admin/issues/3777)) ([49c4dc6](https://github.com/vbenjs/vue-vben-admin/commit/49c4dc646a9d123527577f02ee0d92865da9988e))
|
||||
|
||||
## [2.11.2](https://github.com/vbenjs/vue-vben-admin/compare/v2.11.1...v2.11.2) (2024-04-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **BasicForm:** solve the error about setFieldValue array ([#3775](https://github.com/vbenjs/vue-vben-admin/issues/3775)) ([f5cd3ad](https://github.com/vbenjs/vue-vben-admin/commit/f5cd3ad593ded10a9702cf342d788c4b1540944a))
|
||||
- **ci:** use for package-manager-strict ([d53a5b2](https://github.com/vbenjs/vue-vben-admin/commit/d53a5b22ccadc28f99fc5e9751e3177d349ba8b9))
|
||||
|
||||
## [2.11.1](https://github.com/vbenjs/vue-vben-admin/compare/v2.11.0...v2.11.1) (2024-04-20)
|
||||
|
||||
### Bug Fixes
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# node 构建
|
||||
FROM node:16-alpine as build-stage
|
||||
FROM node:18-alpine as build-stage
|
||||
# 署名
|
||||
MAINTAINER Adoin 'adoin@qq.com'
|
||||
WORKDIR /app
|
||||
|
@@ -62,7 +62,7 @@ Open the project in Gitpod (free online dev environment for GitHub) and start co
|
||||
- Get the project code
|
||||
|
||||
```bash
|
||||
git clone https://github.com/anncwb/vue-vben-admin.git
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
- Install dependencies
|
||||
|
@@ -62,7 +62,7 @@ Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的`vue3
|
||||
- 获取项目代码
|
||||
|
||||
```bash
|
||||
git clone https://github.com/anncwb/vue-vben-admin.git
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
- 安装依赖
|
||||
|
@@ -37,7 +37,7 @@
|
||||
"postcss-less": "^6.0.0",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.2.5",
|
||||
"stylelint": "^16.3.1",
|
||||
"stylelint": "^16.4.0",
|
||||
"stylelint-config-property-sort-order-smacss": "^10.0.0",
|
||||
"stylelint-config-recommended-scss": "^14.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.5.0",
|
||||
|
@@ -21,6 +21,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/node": "^20.12.7",
|
||||
"vite": "^5.2.9"
|
||||
"vite": "^5.2.10"
|
||||
}
|
||||
}
|
||||
|
@@ -33,24 +33,24 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"vite": "^5.2.9"
|
||||
"vite": "^5.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"ant-design-vue": "^4.1.2",
|
||||
"ant-design-vue": "^4.2.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"dotenv": "^16.4.5",
|
||||
"fs-extra": "^11.2.0",
|
||||
"less": "^4.2.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"pkg-types": "^1.0.3",
|
||||
"pkg-types": "^1.1.0",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.75.0",
|
||||
"unocss": "0.59.4",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-dts": "^3.8.3",
|
||||
"vite-plugin-dts": "^3.9.0",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
|
@@ -36,7 +36,7 @@ function defineApplicationConfig(defineOptions: DefineOptions = {}) {
|
||||
});
|
||||
|
||||
const pathResolve = (pathname: string) => resolve(root, '.', pathname);
|
||||
const timestamp = new Date().getTime();
|
||||
|
||||
const applicationConfig: UserConfig = {
|
||||
base: VITE_PUBLIC_PATH,
|
||||
resolve: {
|
||||
@@ -64,7 +64,7 @@ function defineApplicationConfig(defineOptions: DefineOptions = {}) {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
// 入口文件名
|
||||
entryFileNames: `assets/entry/[name]-[hash]-${timestamp}.js`,
|
||||
entryFileNames: 'assets/entry/[name]-[hash].js',
|
||||
manualChunks: {
|
||||
vue: ['vue', 'pinia', 'vue-router'],
|
||||
antd: ['ant-design-vue', '@ant-design/icons-vue'],
|
||||
|
@@ -2,6 +2,7 @@ import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import { type PluginOption } from 'vite';
|
||||
import purgeIcons from 'vite-plugin-purge-icons';
|
||||
import DevTools from 'vite-plugin-vue-devtools';
|
||||
|
||||
import { createAppConfigPlugin } from './appConfig';
|
||||
import { configCompressPlugin } from './compress';
|
||||
@@ -24,6 +25,8 @@ async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyz
|
||||
const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
|
||||
vitePlugins.push(appConfigPlugin);
|
||||
|
||||
vitePlugins.push(DevTools());
|
||||
|
||||
// vite-plugin-html
|
||||
vitePlugins.push(configHtmlPlugin({ isBuild }));
|
||||
|
||||
|
33
package.json
33
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vben-admin",
|
||||
"version": "2.11.1",
|
||||
"version": "2.11.5",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vbenjs/vue-vben-admin/issues"
|
||||
@@ -74,18 +74,18 @@
|
||||
"@logicflow/core": "^1.2.26",
|
||||
"@logicflow/extension": "^1.2.26",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vue/shared": "^3.4.23",
|
||||
"@vue/shared": "^3.4.25",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"ant-design-vue": "^4.1.2",
|
||||
"ant-design-vue": "^4.2.1",
|
||||
"axios": "^1.6.8",
|
||||
"codemirror": "^5.65.16",
|
||||
"cropperjs": "^1.6.1",
|
||||
"cropperjs": "^1.6.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.5.0",
|
||||
"exceljs": "^4.4.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
@@ -101,21 +101,22 @@
|
||||
"tinymce": "^5.10.9",
|
||||
"unocss": "^0.59.4",
|
||||
"vditor": "^3.10.4",
|
||||
"vue": "^3.4.23",
|
||||
"vue-i18n": "^9.13.0",
|
||||
"vue": "^3.4.25",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
"vue-router": "^4.3.2",
|
||||
"vue-types": "^5.1.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vxe-table": "^4.5.22",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.1",
|
||||
"xe-utils": "^3.5.24",
|
||||
"vxe-pc-ui": "^4.0.44",
|
||||
"vxe-table": "^4.7.40",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.4",
|
||||
"xe-utils": "^3.5.28",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.2.2",
|
||||
"@commitlint/cli": "^19.3.0",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@iconify/json": "^2.2.202",
|
||||
"@iconify/json": "^2.2.203",
|
||||
"@purge-icons/generated": "^0.10.0",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
@@ -131,7 +132,7 @@
|
||||
"@vben/ts-config": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/vite-config": "workspace:*",
|
||||
"@vue/compiler-sfc": "^3.4.23",
|
||||
"@vue/compiler-sfc": "^3.4.25",
|
||||
"@vue/test-utils": "^2.4.5",
|
||||
"conventional-changelog-cli": "^4.1.0",
|
||||
"cross-env": "^7.0.3",
|
||||
@@ -145,10 +146,10 @@
|
||||
"turbo": "^1.13.2",
|
||||
"typescript": "^5.4.5",
|
||||
"unbuild": "^2.0.0",
|
||||
"vite": "^5.2.9",
|
||||
"vite": "^5.2.10",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-vue-inspector": "^5.0.0",
|
||||
"vue-tsc": "^2.0.13"
|
||||
"vite-plugin-vue-devtools": "^7.2.0",
|
||||
"vue-tsc": "^2.0.14"
|
||||
},
|
||||
"packageManager": "pnpm@9.0.4",
|
||||
"engines": {
|
||||
|
@@ -32,7 +32,7 @@
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"vue": "^3.4.23"
|
||||
"vue": "^3.4.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vben/types": "workspace:*"
|
||||
|
900
pnpm-lock.yaml
generated
900
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,14 @@
|
||||
<Icon :icon="item.icon || 'mdi:form-select'" :size="20" />
|
||||
</div>
|
||||
<div :class="`${prefixCls}-list__item-text`">
|
||||
{{ item.name }}
|
||||
<!-- 搜索结果包含的字符着色 -->
|
||||
<span
|
||||
v-for="(each, i) in item.chars"
|
||||
:key="i"
|
||||
:class="{ highlight: each.highlight }"
|
||||
>
|
||||
{{ each.char }}
|
||||
</span>
|
||||
</div>
|
||||
<div :class="`${prefixCls}-list__item-enter`">
|
||||
<Icon icon="ant-design:enter-outlined" :size="20" />
|
||||
@@ -254,6 +261,13 @@
|
||||
|
||||
&-text {
|
||||
flex: 1;
|
||||
|
||||
// 搜索结果包含的字符着色
|
||||
& > span {
|
||||
&.highlight {
|
||||
color: lighten(@primary-color, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-enter {
|
||||
|
@@ -13,6 +13,8 @@ export interface SearchResult {
|
||||
name: string;
|
||||
path: string;
|
||||
icon?: string;
|
||||
// 搜索结果包含的字符着色
|
||||
chars: { char: string; highlight: boolean }[];
|
||||
}
|
||||
|
||||
// Translate special characters
|
||||
@@ -49,7 +51,7 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
|
||||
function search(e: ChangeEvent) {
|
||||
e?.stopPropagation();
|
||||
const key = e.target.value;
|
||||
keyword.value = key.trim();
|
||||
keyword.value = key.trim().toLowerCase();
|
||||
if (!key) {
|
||||
searchResult.value = [];
|
||||
return;
|
||||
@@ -68,11 +70,85 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
|
||||
const { name, path, icon, children, hideMenu, meta } = item;
|
||||
if (
|
||||
!hideMenu &&
|
||||
reg.test(name?.toLowerCase()) &&
|
||||
reg.test(name?.toLowerCase() ?? '') &&
|
||||
(!children?.length || meta?.hideChildrenInMenu)
|
||||
) {
|
||||
const chars: { char: string; highlight: boolean }[] = [];
|
||||
|
||||
// 显示字符串
|
||||
const label = (parent?.name ? `${parent.name} > ${name}` : name) ?? '';
|
||||
const labelChars = label.split('');
|
||||
let labelPointer = 0;
|
||||
|
||||
const keywordChars = keyword.value.split('');
|
||||
const keywordLength = keywordChars.length;
|
||||
let keywordPointer = 0;
|
||||
|
||||
// 用于查找完整关键词的匹配
|
||||
let includePointer = 0;
|
||||
|
||||
// 优先查找完整关键词的匹配
|
||||
if (label.toLowerCase().includes(keyword.value.toLowerCase())) {
|
||||
while (includePointer < labelChars.length) {
|
||||
if (
|
||||
label.toLowerCase().slice(includePointer, includePointer + keywordLength) ===
|
||||
keyword.value.toLowerCase()
|
||||
) {
|
||||
chars.push(
|
||||
...label
|
||||
.substring(labelPointer, includePointer)
|
||||
.split('')
|
||||
.map((v) => ({
|
||||
char: v,
|
||||
highlight: false,
|
||||
})),
|
||||
);
|
||||
chars.push(
|
||||
...label
|
||||
.slice(includePointer, includePointer + keywordLength)
|
||||
.split('')
|
||||
.map((v) => ({
|
||||
char: v,
|
||||
highlight: true,
|
||||
})),
|
||||
);
|
||||
includePointer += keywordLength;
|
||||
labelPointer = includePointer;
|
||||
} else {
|
||||
includePointer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查找满足关键词顺序的匹配
|
||||
while (labelPointer < labelChars.length) {
|
||||
keywordPointer = 0;
|
||||
while (keywordPointer < keywordChars.length) {
|
||||
if (keywordChars[keywordPointer] !== void 0 && labelChars[labelPointer] !== void 0) {
|
||||
if (
|
||||
keywordChars[keywordPointer].toLowerCase() ===
|
||||
labelChars[labelPointer].toLowerCase()
|
||||
) {
|
||||
chars.push({
|
||||
char: labelChars[labelPointer],
|
||||
highlight: true,
|
||||
});
|
||||
keywordPointer++;
|
||||
} else {
|
||||
chars.push({
|
||||
char: labelChars[labelPointer],
|
||||
highlight: false,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
keywordPointer++;
|
||||
}
|
||||
labelPointer++;
|
||||
}
|
||||
}
|
||||
ret.push({
|
||||
name: parent?.name ? `${parent.name} > ${name}` : name,
|
||||
name: label,
|
||||
chars,
|
||||
path,
|
||||
icon,
|
||||
});
|
||||
@@ -81,7 +157,36 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
|
||||
ret.push(...handlerSearchResult(children, reg, item));
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
|
||||
// 排序
|
||||
return ret.sort((a, b) => {
|
||||
if (
|
||||
a.name.toLowerCase().includes(keyword.value.toLowerCase()) &&
|
||||
b.name.toLowerCase().includes(keyword.value.toLowerCase())
|
||||
) {
|
||||
// 两者都存在完整关键词的匹配
|
||||
|
||||
// 匹配数量
|
||||
const ca =
|
||||
a.name.toLowerCase().match(new RegExp(keyword.value.toLowerCase(), 'g'))?.length ?? 0;
|
||||
const cb =
|
||||
b.name.toLowerCase().match(new RegExp(keyword.value.toLowerCase(), 'g'))?.length ?? 0;
|
||||
|
||||
// 匹配数量越多的优先显示,数量相同的按字符串排序
|
||||
return ca === cb ? a.name.toLowerCase().localeCompare(b.name.toLowerCase()) : cb - ca;
|
||||
} else {
|
||||
if (a.name.toLowerCase().includes(keyword.value.toLowerCase())) {
|
||||
// 完整关键词的匹配优先
|
||||
return -1;
|
||||
} else if (b.name.toLowerCase().includes(keyword.value.toLowerCase())) {
|
||||
// 完整关键词的匹配优先
|
||||
return 1;
|
||||
} else {
|
||||
// 按字符串排序
|
||||
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Activate when the mouse moves to a certain line
|
||||
|
@@ -6,6 +6,7 @@
|
||||
:mode="mode"
|
||||
:readonly="readonly"
|
||||
:bordered="bordered"
|
||||
:config="config"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -14,6 +15,7 @@
|
||||
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
|
||||
import { isString } from '@/utils/is';
|
||||
import { MODE } from './typing';
|
||||
import type { EditorConfiguration } from 'codemirror';
|
||||
|
||||
const props = defineProps({
|
||||
value: { type: [Object, String] as PropType<Record<string, any> | string> },
|
||||
@@ -28,6 +30,7 @@
|
||||
readonly: { type: Boolean },
|
||||
autoFormat: { type: Boolean, default: true },
|
||||
bordered: { type: Boolean, default: false },
|
||||
config: { type: Object as PropType<EditorConfiguration>, default: () => {} },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change', 'update:value', 'format-error']);
|
||||
|
@@ -22,15 +22,22 @@
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import CodeMirror from 'codemirror';
|
||||
import { MODE } from './../typing';
|
||||
import type { EditorConfiguration } from 'codemirror';
|
||||
import { MODE, parserDynamicImport } from './../typing';
|
||||
// css
|
||||
import './codemirror.css';
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
import 'codemirror/theme/idea.css';
|
||||
import 'codemirror/theme/material-palenight.css';
|
||||
// modes
|
||||
import 'codemirror/mode/javascript/javascript';
|
||||
import 'codemirror/mode/css/css';
|
||||
import 'codemirror/mode/htmlmixed/htmlmixed';
|
||||
|
||||
// 代码段折叠功能
|
||||
import 'codemirror/addon/fold/foldgutter.css';
|
||||
import 'codemirror/addon/fold/foldcode.js';
|
||||
import 'codemirror/addon/fold/foldgutter';
|
||||
import 'codemirror/addon/fold/brace-fold';
|
||||
import 'codemirror/addon/fold/comment-fold';
|
||||
import 'codemirror/addon/fold/markdown-fold';
|
||||
import 'codemirror/addon/fold/xml-fold';
|
||||
import 'codemirror/addon/fold/indent-fold';
|
||||
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
@@ -44,6 +51,7 @@
|
||||
value: { type: String, default: '' },
|
||||
readonly: { type: Boolean, default: false },
|
||||
bordered: { type: Boolean, default: false },
|
||||
config: { type: Object as PropType<EditorConfiguration>, default: () => {} },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
@@ -66,7 +74,8 @@
|
||||
{ flush: 'post' },
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
watchEffect(async () => {
|
||||
await parserDynamicImport(props.mode)();
|
||||
editor?.setOption('mode', props.mode);
|
||||
});
|
||||
|
||||
@@ -96,7 +105,7 @@
|
||||
autoCloseBrackets: true,
|
||||
autoCloseTags: true,
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers'],
|
||||
gutters: ['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||
};
|
||||
|
||||
editor = CodeMirror(el.value!, {
|
||||
@@ -108,6 +117,7 @@
|
||||
lineWrapping: true,
|
||||
lineNumbers: true,
|
||||
...addonOptions,
|
||||
...props.config,
|
||||
});
|
||||
editor?.setValue(props.value);
|
||||
setTheme();
|
||||
|
@@ -1,529 +0,0 @@
|
||||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
--base: #545281;
|
||||
--comment: hsl(210deg 25% 60%);
|
||||
--keyword: #af4ab1;
|
||||
--variable: #0055d1;
|
||||
--function: #c25205;
|
||||
--string: #2ba46d;
|
||||
--number: #c25205;
|
||||
--tags: #d00;
|
||||
--qualifier: #ff6032;
|
||||
--important: var(--string);
|
||||
|
||||
position: relative;
|
||||
height: auto;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-family: var(--font-code);
|
||||
background: white;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
min-height: 1px; /* prevents collapsing before first draw */
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler,
|
||||
.CodeMirror-gutter-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
min-height: 100%;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.CodeMirror-linenumber {
|
||||
min-width: 20px;
|
||||
padding: 0 3px 0 5px;
|
||||
color: var(--comment);
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker-subtle {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* FOLD GUTTER */
|
||||
|
||||
.CodeMirror-foldmarker {
|
||||
font-family: arial;
|
||||
line-height: 0.3;
|
||||
color: #414141;
|
||||
text-shadow:
|
||||
#f96 1px 1px 2px,
|
||||
#f96 -1px -1px 2px,
|
||||
#f96 1px -1px 2px,
|
||||
#f96 -1px 1px 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.CodeMirror-foldgutter {
|
||||
width: 0.7em;
|
||||
}
|
||||
|
||||
.CodeMirror-foldgutter-open,
|
||||
.CodeMirror-foldgutter-folded {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.CodeMirror-foldgutter-open::after,
|
||||
.CodeMirror-foldgutter-folded::after {
|
||||
position: relative;
|
||||
top: -0.1em;
|
||||
display: inline-block;
|
||||
font-size: 0.8em;
|
||||
content: '>';
|
||||
opacity: 0.8;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.CodeMirror-foldgutter-folded::after {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
pointer-events: none;
|
||||
border-right: none;
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
|
||||
.cm-fat-cursor .CodeMirror-cursor {
|
||||
width: auto;
|
||||
background: #7e7;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cm-fat-cursor-mark {
|
||||
background-color: rgb(20 255 20 / 50%);
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
}
|
||||
|
||||
.cm-animate-fat-cursor {
|
||||
width: auto;
|
||||
background-color: #7e7;
|
||||
border: 0;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
}
|
||||
@keyframes blink {
|
||||
50% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@keyframes blink {
|
||||
50% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@keyframes blink {
|
||||
50% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.cm-tab {
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.CodeMirror-rulers {
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
right: 0;
|
||||
bottom: -20px;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-ruler {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
.cm-s-default.CodeMirror {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-header {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-quote {
|
||||
color: #090;
|
||||
}
|
||||
|
||||
.cm-negative {
|
||||
color: #d44;
|
||||
}
|
||||
|
||||
.cm-positive {
|
||||
color: #292;
|
||||
}
|
||||
|
||||
.cm-header,
|
||||
.cm-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cm-em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.cm-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cm-strikethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-atom,
|
||||
.cm-s-default .cm-def,
|
||||
.cm-s-default .cm-property,
|
||||
.cm-s-default .cm-variable-2,
|
||||
.cm-s-default .cm-variable-3,
|
||||
.cm-s-default .cm-punctuation {
|
||||
color: var(--base);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-hr,
|
||||
.cm-s-default .cm-comment {
|
||||
color: var(--comment);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-attribute,
|
||||
.cm-s-default .cm-keyword {
|
||||
color: var(--keyword);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-variable {
|
||||
color: var(--variable);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-bracket,
|
||||
.cm-s-default .cm-tag {
|
||||
color: var(--tags);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-number {
|
||||
color: var(--number);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-string,
|
||||
.cm-s-default .cm-string-2 {
|
||||
color: var(--string);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-type {
|
||||
color: #085;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-meta {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-qualifier {
|
||||
color: var(--qualifier);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-builtin {
|
||||
color: #7539ff;
|
||||
}
|
||||
|
||||
.cm-s-default .cm-link {
|
||||
color: var(--flash);
|
||||
}
|
||||
|
||||
.cm-s-default .cm-error {
|
||||
color: #ff008c;
|
||||
}
|
||||
|
||||
.cm-invalidchar {
|
||||
color: #ff008c;
|
||||
}
|
||||
|
||||
.CodeMirror-composing {
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
/* Default styles for common addons */
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {
|
||||
color: #0b0;
|
||||
}
|
||||
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||
color: #a22;
|
||||
}
|
||||
|
||||
.CodeMirror-matchingtag {
|
||||
background: rgb(255 150 0 / 30%);
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background {
|
||||
background: #e8f2ff;
|
||||
}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror-scroll {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding-bottom: 30px;
|
||||
margin-right: -30px;
|
||||
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px;
|
||||
overflow: scroll !important; /* Things will break if this is overridden */
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
}
|
||||
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
margin-bottom: 20px !important;
|
||||
border-right: 30px solid transparent;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actual scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar,
|
||||
.CodeMirror-hscrollbar,
|
||||
.CodeMirror-scrollbar-filler,
|
||||
.CodeMirror-gutter-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar {
|
||||
top: 0;
|
||||
right: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-filler {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
margin-bottom: -30px;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-wrapper ::selection {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.CodeMirrorwrapper ::selection {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.CodeMirror pre {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
word-wrap: normal;
|
||||
white-space: pre;
|
||||
background: transparent;
|
||||
border-width: 0;
|
||||
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
border-radius: 0;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
font-variant-ligatures: contextual;
|
||||
}
|
||||
|
||||
.CodeMirror-wrap pre {
|
||||
word-break: normal;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0.1px; /* Force widget margins to stay inside of the container */
|
||||
}
|
||||
|
||||
.CodeMirror-rtl pre {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
.CodeMirror-scroll,
|
||||
.CodeMirror-sizer,
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-measure pre {
|
||||
position: static;
|
||||
}
|
||||
|
||||
div.CodeMirror-cursors {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
div.CodeMirror-dragcursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
|
||||
.CodeMirror-focused .CodeMirror-selected {
|
||||
background: #d7d4f0;
|
||||
}
|
||||
|
||||
.CodeMirror-crosshair {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.CodeMirror-line::selection,
|
||||
.CodeMirror-line > span::selection,
|
||||
.CodeMirror-line > span > span::selection {
|
||||
background: #d7d4f0;
|
||||
}
|
||||
|
||||
.cm-searching {
|
||||
background-color: #ffa;
|
||||
background-color: rgb(255 255 0 / 40%);
|
||||
}
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
.cm-force-border {
|
||||
padding-right: 0.1px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext {
|
||||
background: none;
|
||||
}
|
@@ -1,5 +1,247 @@
|
||||
export enum MODE {
|
||||
JSON = 'application/json',
|
||||
HTML = 'htmlmixed',
|
||||
JS = 'javascript',
|
||||
APL = 'apl',
|
||||
ASCIIARMOR = 'asciiarmor',
|
||||
ASTERISK = 'asterisk',
|
||||
BRAINFUCK = 'brainfuck',
|
||||
CLIKE = 'clike',
|
||||
CLOJURE = 'clojure',
|
||||
CMAKE = 'cmake',
|
||||
COBOL = 'cobol',
|
||||
COFFEESCRIPT = 'coffeescript',
|
||||
COMMONLISP = 'commonlisp',
|
||||
CRYSTAL = 'crystal',
|
||||
CSS = 'css',
|
||||
CYPHER = 'cypher',
|
||||
D = 'd',
|
||||
DART = 'dart',
|
||||
DIFF = 'diff',
|
||||
DJANGO = 'django',
|
||||
DOCKERFILE = 'dockerfile',
|
||||
DTD = 'dtd',
|
||||
DYLAN = 'dylan',
|
||||
EBNF = 'ebnf',
|
||||
ECL = 'ecl',
|
||||
EIFFEL = 'eiffel',
|
||||
ELM = 'elm',
|
||||
ERLANG = 'erlang',
|
||||
FACTOR = 'factor',
|
||||
FCL = 'fcl',
|
||||
FORTH = 'forth',
|
||||
FORTRAN = 'fortran',
|
||||
GAS = 'gas',
|
||||
GFM = 'gfm',
|
||||
GHERKIN = 'gherkin',
|
||||
GO = 'go',
|
||||
GROOVY = 'groovy',
|
||||
HAML = 'haml',
|
||||
HANDLEBARS = 'handlebars',
|
||||
HASKELL = 'haskell',
|
||||
HAXE = 'haxe',
|
||||
HTMLEMBEDDED = 'htmlembedded',
|
||||
HTMLMIXED = 'htmlmixed',
|
||||
HTTP = 'http',
|
||||
IDL = 'idl',
|
||||
JAVASCRIPT = 'javascript',
|
||||
JINJA2 = 'jinja2',
|
||||
JSX = 'jsx',
|
||||
JULIA = 'julia',
|
||||
LIVESCRIPT = 'livescript',
|
||||
LUA = 'lua',
|
||||
MARKDOWN = 'markdown',
|
||||
MATHEMATICA = 'mathematica',
|
||||
MBOX = 'mbox',
|
||||
MIRC = 'mirc',
|
||||
MLLIKE = 'mllike',
|
||||
MODELICA = 'modelica',
|
||||
MSCGEN = 'mscgen',
|
||||
MUMPS = 'mumps',
|
||||
NGINX = 'nginx',
|
||||
NSIS = 'nsis',
|
||||
NTRIPLES = 'ntriples',
|
||||
OCTAVE = 'octave',
|
||||
OZ = 'oz',
|
||||
PASCAL = 'pascal',
|
||||
PEGJS = 'pegjs',
|
||||
PERL = 'perl',
|
||||
PHP = 'php',
|
||||
PIG = 'pig',
|
||||
POWERSHELL = 'powershell',
|
||||
PROPERTIES = 'properties',
|
||||
PROTOBUF = 'protobuf',
|
||||
PUG = 'pug',
|
||||
PUPPET = 'puppet',
|
||||
PYTHON = 'python',
|
||||
Q = 'q',
|
||||
R = 'r',
|
||||
RPM = 'rpm',
|
||||
RST = 'rst',
|
||||
RUBY = 'ruby',
|
||||
RUST = 'rust',
|
||||
SAS = 'sas',
|
||||
SASS = 'sass',
|
||||
SCHEME = 'scheme',
|
||||
SHELL = 'shell',
|
||||
SIEVE = 'sieve',
|
||||
SLIM = 'slim',
|
||||
SMALLTALK = 'smalltalk',
|
||||
SMARTY = 'smarty',
|
||||
SOLR = 'solr',
|
||||
SOY = 'soy',
|
||||
SPARQL = 'sparql',
|
||||
SPREADSHEET = 'spreadsheet',
|
||||
SQL = 'sql',
|
||||
STEX = 'stex',
|
||||
STYLUS = 'stylus',
|
||||
SWIFT = 'swift',
|
||||
TCL = 'tcl',
|
||||
TEXTILE = 'textile',
|
||||
TIDDLYWIKI = 'tiddlywiki',
|
||||
TIKI = 'tiki',
|
||||
TOML = 'toml',
|
||||
TORNADO = 'tornado',
|
||||
TROFF = 'troff',
|
||||
TTCN = 'ttcn',
|
||||
TURTLE = 'turtle',
|
||||
TWIG = 'twig',
|
||||
VB = 'vb',
|
||||
VBSCRIPT = 'vbscript',
|
||||
VELOCITY = 'velocity',
|
||||
VERILOG = 'verilog',
|
||||
VHDL = 'vhdl',
|
||||
VUE = 'vue',
|
||||
WAST = 'wast',
|
||||
WEBIDL = 'webidl',
|
||||
XML = 'xml',
|
||||
XQUERY = 'xquery',
|
||||
YACAS = 'yacas',
|
||||
YAML = 'yaml',
|
||||
Z80 = 'z80',
|
||||
}
|
||||
/**
|
||||
* @description: DynamicImport codemirror
|
||||
*/
|
||||
export function parserDynamicImport(str: MODE): () => Promise<any> {
|
||||
const dynamicArray = {
|
||||
// adapt before demo
|
||||
'application/json': async () => await import('codemirror/mode/javascript/javascript'),
|
||||
apl: async () => await import('codemirror/mode/apl/apl'),
|
||||
asciiarmor: async () => await import('codemirror/mode/asciiarmor/asciiarmor'),
|
||||
asterisk: async () => await import('codemirror/mode/asterisk/asterisk'),
|
||||
brainfuck: async () => await import('codemirror/mode/brainfuck/brainfuck'),
|
||||
clike: async () => await import('codemirror/mode/clike/clike'),
|
||||
clojure: async () => await import('codemirror/mode/clojure/clojure'),
|
||||
cmake: async () => await import('codemirror/mode/cmake/cmake'),
|
||||
cobol: async () => await import('codemirror/mode/cobol/cobol'),
|
||||
coffeescript: async () => await import('codemirror/mode/coffeescript/coffeescript'),
|
||||
commonlisp: async () => await import('codemirror/mode/commonlisp/commonlisp'),
|
||||
crystal: async () => await import('codemirror/mode/crystal/crystal'),
|
||||
css: async () => await import('codemirror/mode/css/css'),
|
||||
cypher: async () => await import('codemirror/mode/cypher/cypher'),
|
||||
d: async () => await import('codemirror/mode/d/d'),
|
||||
dart: async () => await import('codemirror/mode/dart/dart'),
|
||||
diff: async () => await import('codemirror/mode/diff/diff'),
|
||||
django: async () => await import('codemirror/mode/django/django'),
|
||||
dockerfile: async () => await import('codemirror/mode/dockerfile/dockerfile'),
|
||||
dtd: async () => await import('codemirror/mode/dtd/dtd'),
|
||||
dylan: async () => await import('codemirror/mode/dylan/dylan'),
|
||||
ebnf: async () => await import('codemirror/mode/ebnf/ebnf'),
|
||||
ecl: async () => await import('codemirror/mode/ecl/ecl'),
|
||||
eiffel: async () => await import('codemirror/mode/eiffel/eiffel'),
|
||||
elm: async () => await import('codemirror/mode/elm/elm'),
|
||||
erlang: async () => await import('codemirror/mode/erlang/erlang'),
|
||||
factor: async () => await import('codemirror/mode/factor/factor'),
|
||||
fcl: async () => await import('codemirror/mode/fcl/fcl'),
|
||||
forth: async () => await import('codemirror/mode/forth/forth'),
|
||||
fortran: async () => await import('codemirror/mode/fortran/fortran'),
|
||||
gas: async () => await import('codemirror/mode/gas/gas'),
|
||||
gfm: async () => await import('codemirror/mode/gfm/gfm'),
|
||||
gherkin: async () => await import('codemirror/mode/gherkin/gherkin'),
|
||||
go: async () => await import('codemirror/mode/go/go'),
|
||||
groovy: async () => await import('codemirror/mode/groovy/groovy'),
|
||||
haml: async () => await import('codemirror/mode/haml/haml'),
|
||||
handlebars: async () => await import('codemirror/mode/handlebars/handlebars'),
|
||||
haskell: async () => await import('codemirror/mode/haskell/haskell'),
|
||||
haxe: async () => await import('codemirror/mode/haxe/haxe'),
|
||||
htmlembedded: async () => await import('codemirror/mode/htmlembedded/htmlembedded'),
|
||||
htmlmixed: async () => await import('codemirror/mode/htmlmixed/htmlmixed'),
|
||||
http: async () => await import('codemirror/mode/http/http'),
|
||||
idl: async () => await import('codemirror/mode/idl/idl'),
|
||||
javascript: async () => await import('codemirror/mode/javascript/javascript'),
|
||||
jinja2: async () => await import('codemirror/mode/jinja2/jinja2'),
|
||||
jsx: async () => await import('codemirror/mode/jsx/jsx'),
|
||||
julia: async () => await import('codemirror/mode/julia/julia'),
|
||||
livescript: async () => await import('codemirror/mode/livescript/livescript'),
|
||||
lua: async () => await import('codemirror/mode/lua/lua'),
|
||||
markdown: async () => await import('codemirror/mode/markdown/markdown'),
|
||||
mathematica: async () => await import('codemirror/mode/mathematica/mathematica'),
|
||||
mbox: async () => await import('codemirror/mode/mbox/mbox'),
|
||||
mirc: async () => await import('codemirror/mode/mirc/mirc'),
|
||||
mllike: async () => await import('codemirror/mode/mllike/mllike'),
|
||||
modelica: async () => await import('codemirror/mode/modelica/modelica'),
|
||||
mscgen: async () => await import('codemirror/mode/mscgen/mscgen'),
|
||||
mumps: async () => await import('codemirror/mode/mumps/mumps'),
|
||||
nginx: async () => await import('codemirror/mode/nginx/nginx'),
|
||||
nsis: async () => await import('codemirror/mode/nsis/nsis'),
|
||||
ntriples: async () => await import('codemirror/mode/ntriples/ntriples'),
|
||||
octave: async () => await import('codemirror/mode/octave/octave'),
|
||||
oz: async () => await import('codemirror/mode/oz/oz'),
|
||||
pascal: async () => await import('codemirror/mode/pascal/pascal'),
|
||||
pegjs: async () => await import('codemirror/mode/pegjs/pegjs'),
|
||||
perl: async () => await import('codemirror/mode/perl/perl'),
|
||||
php: async () => await import('codemirror/mode/php/php'),
|
||||
pig: async () => await import('codemirror/mode/pig/pig'),
|
||||
powershell: async () => await import('codemirror/mode/powershell/powershell'),
|
||||
properties: async () => await import('codemirror/mode/properties/properties'),
|
||||
protobuf: async () => await import('codemirror/mode/protobuf/protobuf'),
|
||||
pug: async () => await import('codemirror/mode/pug/pug'),
|
||||
puppet: async () => await import('codemirror/mode/puppet/puppet'),
|
||||
python: async () => await import('codemirror/mode/python/python'),
|
||||
q: async () => await import('codemirror/mode/q/q'),
|
||||
r: async () => await import('codemirror/mode/r/r'),
|
||||
rpm: async () => await import('codemirror/mode/rpm/rpm'),
|
||||
rst: async () => await import('codemirror/mode/rst/rst'),
|
||||
ruby: async () => await import('codemirror/mode/ruby/ruby'),
|
||||
rust: async () => await import('codemirror/mode/rust/rust'),
|
||||
sas: async () => await import('codemirror/mode/sas/sas'),
|
||||
sass: async () => await import('codemirror/mode/sass/sass'),
|
||||
scheme: async () => await import('codemirror/mode/scheme/scheme'),
|
||||
shell: async () => await import('codemirror/mode/shell/shell'),
|
||||
sieve: async () => await import('codemirror/mode/sieve/sieve'),
|
||||
slim: async () => await import('codemirror/mode/slim/slim'),
|
||||
smalltalk: async () => await import('codemirror/mode/smalltalk/smalltalk'),
|
||||
smarty: async () => await import('codemirror/mode/smarty/smarty'),
|
||||
solr: async () => await import('codemirror/mode/solr/solr'),
|
||||
soy: async () => await import('codemirror/mode/soy/soy'),
|
||||
sparql: async () => await import('codemirror/mode/sparql/sparql'),
|
||||
spreadsheet: async () => await import('codemirror/mode/spreadsheet/spreadsheet'),
|
||||
sql: async () => await import('codemirror/mode/sql/sql'),
|
||||
stex: async () => await import('codemirror/mode/stex/stex'),
|
||||
stylus: async () => await import('codemirror/mode/stylus/stylus'),
|
||||
swift: async () => await import('codemirror/mode/swift/swift'),
|
||||
tcl: async () => await import('codemirror/mode/tcl/tcl'),
|
||||
textile: async () => await import('codemirror/mode/textile/textile'),
|
||||
tiddlywiki: async () => await import('codemirror/mode/tiddlywiki/tiddlywiki'),
|
||||
tiki: async () => await import('codemirror/mode/tiki/tiki'),
|
||||
toml: async () => await import('codemirror/mode/toml/toml'),
|
||||
tornado: async () => await import('codemirror/mode/tornado/tornado'),
|
||||
troff: async () => await import('codemirror/mode/troff/troff'),
|
||||
ttcn: async () => await import('codemirror/mode/ttcn/ttcn'),
|
||||
turtle: async () => await import('codemirror/mode/turtle/turtle'),
|
||||
twig: async () => await import('codemirror/mode/twig/twig'),
|
||||
vb: async () => await import('codemirror/mode/vb/vb'),
|
||||
vbscript: async () => await import('codemirror/mode/vbscript/vbscript'),
|
||||
velocity: async () => await import('codemirror/mode/velocity/velocity'),
|
||||
verilog: async () => await import('codemirror/mode/verilog/verilog'),
|
||||
vhdl: async () => await import('codemirror/mode/vhdl/vhdl'),
|
||||
vue: async () => await import('codemirror/mode/vue/vue'),
|
||||
wast: async () => await import('codemirror/mode/wast/wast'),
|
||||
webidl: async () => await import('codemirror/mode/webidl/webidl'),
|
||||
xml: async () => await import('codemirror/mode/xml/xml'),
|
||||
xquery: async () => await import('codemirror/mode/xquery/xquery'),
|
||||
yacas: async () => await import('codemirror/mode/yacas/yacas'),
|
||||
yaml: async () => await import('codemirror/mode/yaml/yaml'),
|
||||
z80: async () => await import('codemirror/mode/z80/z80'),
|
||||
};
|
||||
return dynamicArray[str];
|
||||
}
|
||||
|
@@ -151,7 +151,7 @@
|
||||
fileReader.onerror = () => {
|
||||
emit('cropendError');
|
||||
};
|
||||
}, 'image/png');
|
||||
}, 'image/jpeg');
|
||||
}
|
||||
|
||||
// Get a circular picture canvas
|
||||
|
@@ -54,7 +54,7 @@
|
||||
|
||||
import { useFormValues } from './hooks/useFormValues';
|
||||
import useAdvanced from './hooks/useAdvanced';
|
||||
import { useFormEvents } from './hooks/useFormEvents';
|
||||
import { itemIsUploadComponent, useFormEvents } from './hooks/useFormEvents';
|
||||
import { createFormContext } from './hooks/useFormContext';
|
||||
import { useAutoFocus } from './hooks/useAutoFocus';
|
||||
import { useModalContext } from '@/components/Modal';
|
||||
@@ -64,6 +64,7 @@
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { TableActionType } from '@/components/Table';
|
||||
import { isArray, isFunction } from '@/utils/is';
|
||||
|
||||
defineOptions({ name: 'BasicForm' });
|
||||
|
||||
@@ -123,14 +124,28 @@
|
||||
const getBindValue = computed(() => ({ ...attrs, ...props, ...unref(getProps) }) as AntFormProps);
|
||||
|
||||
const getSchema = computed((): FormSchema[] => {
|
||||
const schemas: FormSchema[] = cloneDeep(unref(schemaRef) || (unref(getProps).schemas as any));
|
||||
const schemas: (FormSchema & { ifshow2?: boolean })[] = cloneDeep(
|
||||
unref(schemaRef) || (unref(getProps).schemas as any),
|
||||
);
|
||||
for (const schema of schemas) {
|
||||
const {
|
||||
defaultValue,
|
||||
component,
|
||||
componentProps = {},
|
||||
isHandleDateDefaultValue = true,
|
||||
field,
|
||||
isHandleDefaultValue = true,
|
||||
valueFormat,
|
||||
ifShow,
|
||||
} = schema;
|
||||
|
||||
//fix:修复showAdvancedButton为true时,FormSchema中ifshow是与model有关的函数时候,查询按钮位置不重新计算的问题。
|
||||
if (unref(getProps).showAdvancedButton) {
|
||||
schema.ifshow2 = isFunction(ifShow)
|
||||
? ifShow({ schema, values: formModel, model: formModel, field })
|
||||
: ifShow;
|
||||
}
|
||||
|
||||
// handle date type
|
||||
if (
|
||||
isHandleDateDefaultValue &&
|
||||
@@ -161,6 +176,24 @@
|
||||
schema.defaultValue = def;
|
||||
}
|
||||
}
|
||||
// handle upload type
|
||||
if (defaultValue && itemIsUploadComponent(schema?.component)) {
|
||||
if (isArray(defaultValue)) {
|
||||
schema.defaultValue = defaultValue;
|
||||
} else if (typeof defaultValue == 'string') {
|
||||
schema.defaultValue = [defaultValue];
|
||||
}
|
||||
}
|
||||
|
||||
// handle schema.valueFormat
|
||||
if (isHandleDefaultValue && defaultValue && component && isFunction(valueFormat)) {
|
||||
schema.defaultValue = valueFormat({
|
||||
value: defaultValue,
|
||||
schema,
|
||||
model: formModel,
|
||||
field,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (unref(getProps).showAdvancedButton) {
|
||||
return schemas.filter(
|
||||
@@ -207,6 +240,7 @@
|
||||
removeSchemaByField,
|
||||
resetFields,
|
||||
scrollToField,
|
||||
resetDefaultField,
|
||||
} = useFormEvents({
|
||||
emit,
|
||||
getProps,
|
||||
@@ -305,6 +339,7 @@
|
||||
validate,
|
||||
submit: handleSubmit,
|
||||
scrollToField: scrollToField,
|
||||
resetDefaultField,
|
||||
};
|
||||
|
||||
const getFormActionBindProps = computed(
|
||||
@@ -337,11 +372,20 @@
|
||||
// margin-bottom: 20px;
|
||||
// }
|
||||
|
||||
&.suffix-item {
|
||||
&.suffix-item,
|
||||
&.prefix-item {
|
||||
.ant-form-item-children {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.prefix {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-top: 1px;
|
||||
padding-right: 6px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.suffix {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
@@ -69,6 +69,14 @@
|
||||
displayRenderArray: {
|
||||
type: Array,
|
||||
},
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change', 'defaultChange']);
|
||||
@@ -112,19 +120,25 @@
|
||||
}, [] as Option[]);
|
||||
}
|
||||
|
||||
async function initialFetch() {
|
||||
const api = props.api;
|
||||
async function fetch() {
|
||||
let { api, beforeFetch, initFetchParams, afterFetch, resultField } = props;
|
||||
if (!api || !isFunction(api)) return;
|
||||
apiData.value = [];
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await api(props.initFetchParams);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
initFetchParams = (await beforeFetch(initFetchParams)) || initFetchParams;
|
||||
}
|
||||
let res = await api(initFetchParams);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
if (Array.isArray(res)) {
|
||||
apiData.value = res;
|
||||
return;
|
||||
}
|
||||
if (props.resultField) {
|
||||
apiData.value = get(res, props.resultField) || [];
|
||||
if (resultField) {
|
||||
apiData.value = get(res, resultField) || [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
@@ -136,20 +150,26 @@
|
||||
const loadData: CascaderProps['loadData'] = async (selectedOptions) => {
|
||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||
targetOption.loading = true;
|
||||
|
||||
const api = props.api;
|
||||
let { api, beforeFetch, afterFetch, resultField, apiParamKey } = props;
|
||||
if (!api || !isFunction(api)) return;
|
||||
try {
|
||||
const res = await api({
|
||||
[props.apiParamKey]: Reflect.get(targetOption, 'value'),
|
||||
});
|
||||
let param = {
|
||||
[apiParamKey]: Reflect.get(targetOption, 'value'),
|
||||
};
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
param = (await beforeFetch(param)) || param;
|
||||
}
|
||||
let res = await api(param);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
if (Array.isArray(res)) {
|
||||
const children = generatorOptions(res);
|
||||
targetOption.children = children;
|
||||
return;
|
||||
}
|
||||
if (props.resultField) {
|
||||
const children = generatorOptions(get(res, props.resultField) || []);
|
||||
if (resultField) {
|
||||
const children = generatorOptions(get(res, resultField) || []);
|
||||
targetOption.children = children;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -162,7 +182,7 @@
|
||||
watch(
|
||||
() => props.immediate,
|
||||
() => {
|
||||
props.immediate && initialFetch();
|
||||
props.immediate && fetch();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
@@ -172,7 +192,7 @@
|
||||
watch(
|
||||
() => props.initFetchParams,
|
||||
() => {
|
||||
!unref(isFirstLoad) && initialFetch();
|
||||
!unref(isFirstLoad) && fetch();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
@@ -57,6 +57,14 @@
|
||||
labelField: propTypes.string.def('label'),
|
||||
valueField: propTypes.string.def('value'),
|
||||
immediate: propTypes.bool.def(true),
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['options-change', 'change', 'update:value']);
|
||||
@@ -95,19 +103,25 @@
|
||||
);
|
||||
|
||||
async function fetch() {
|
||||
const api = props.api;
|
||||
let { api, beforeFetch, afterFetch, params, resultField } = props;
|
||||
if (!api || !isFunction(api)) return;
|
||||
options.value = [];
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await api(props.params);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
params = (await beforeFetch(params)) || params;
|
||||
}
|
||||
let res = await api(params);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
if (Array.isArray(res)) {
|
||||
options.value = res;
|
||||
emitChange();
|
||||
return;
|
||||
}
|
||||
if (props.resultField) {
|
||||
options.value = get(res, props.resultField) || [];
|
||||
if (resultField) {
|
||||
options.value = get(res, resultField) || [];
|
||||
}
|
||||
emitChange();
|
||||
} catch (error) {
|
||||
|
@@ -3,6 +3,7 @@
|
||||
@dropdown-visible-change="handleFetch"
|
||||
v-bind="$attrs"
|
||||
@change="handleChange"
|
||||
@search="debounceSearchFn"
|
||||
:options="getOptions"
|
||||
v-model:value="state"
|
||||
>
|
||||
@@ -20,26 +21,41 @@
|
||||
</template>
|
||||
</Select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType, ref, computed, unref, watch } from 'vue';
|
||||
import { computed, PropType, ref, unref, watch } from 'vue';
|
||||
import { Select } from 'ant-design-vue';
|
||||
import type { SelectValue } from 'ant-design-vue/es/select';
|
||||
import { isFunction } from '@/utils/is';
|
||||
import { isEmpty, isFunction } from '@/utils/is';
|
||||
import { useRuleFormItem } from '@/hooks/component/useFormItem';
|
||||
import { get, omit, isEqual } from 'lodash-es';
|
||||
import { assignIn, get, isEqual, omit } from 'lodash-es';
|
||||
import { LoadingOutlined } from '@ant-design/icons-vue';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
|
||||
type OptionsItem = { label?: string; value?: string; disabled?: boolean; [name: string]: any };
|
||||
|
||||
type ApiSearchOption = {
|
||||
// 展示搜索
|
||||
show?: boolean;
|
||||
// 待搜索字段名
|
||||
searchName?: string;
|
||||
// 是否允许空搜索
|
||||
emptySearch?: boolean;
|
||||
// 搜索前置方法
|
||||
beforeFetch?: (value?: string) => Promise<string>;
|
||||
// 拦截方法
|
||||
interceptFetch?: (value?: string) => Promise<boolean>;
|
||||
};
|
||||
|
||||
defineOptions({ name: 'ApiSelect', inheritAttrs: false });
|
||||
|
||||
const props = defineProps({
|
||||
value: { type: [Array, Object, String, Number] as PropType<SelectValue> },
|
||||
numberToString: propTypes.bool,
|
||||
api: {
|
||||
type: Function as PropType<(arg?: any) => Promise<OptionsItem[] | Recordable<any>>>,
|
||||
type: Function as PropType<(arg?: any) => Promise<OptionsItem[] | Recordable>>,
|
||||
default: null,
|
||||
},
|
||||
// api params
|
||||
@@ -54,6 +70,18 @@
|
||||
type: Array<OptionsItem>,
|
||||
default: [],
|
||||
},
|
||||
apiSearch: {
|
||||
type: Object as PropType<ApiSearchOption>,
|
||||
default: () => null,
|
||||
},
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['options-change', 'change', 'update:value']);
|
||||
@@ -64,6 +92,7 @@
|
||||
// 首次是否加载过了
|
||||
const isFirstLoaded = ref(false);
|
||||
const emitData = ref<OptionsItem[]>([]);
|
||||
const searchParams = ref<any>({});
|
||||
const { t } = useI18n();
|
||||
|
||||
// Embedded in the form, just use the hook binding to perform form verification
|
||||
@@ -102,21 +131,40 @@
|
||||
{ deep: true, immediate: props.immediate },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => searchParams.value,
|
||||
(value, oldValue) => {
|
||||
if (isEmpty(value) || isEqual(value, oldValue)) return;
|
||||
(async () => {
|
||||
await fetch();
|
||||
searchParams.value = {};
|
||||
})();
|
||||
},
|
||||
{ deep: true, immediate: props.immediate },
|
||||
);
|
||||
|
||||
async function fetch() {
|
||||
const api = props.api;
|
||||
let { api, beforeFetch, afterFetch, params, resultField } = props;
|
||||
if (!api || !isFunction(api) || loading.value) return;
|
||||
optionsRef.value = [];
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await api(props.params);
|
||||
let apiParams = assignIn({}, params, searchParams.value);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
apiParams = (await beforeFetch(apiParams)) || apiParams;
|
||||
}
|
||||
let res = await api(apiParams);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
isFirstLoaded.value = true;
|
||||
if (Array.isArray(res)) {
|
||||
optionsRef.value = res;
|
||||
emitChange();
|
||||
return;
|
||||
}
|
||||
if (props.resultField) {
|
||||
optionsRef.value = get(res, props.resultField) || [];
|
||||
if (resultField) {
|
||||
optionsRef.value = get(res, resultField) || [];
|
||||
}
|
||||
emitChange();
|
||||
} catch (error) {
|
||||
@@ -133,11 +181,43 @@
|
||||
if (props.alwaysLoad) {
|
||||
await fetch();
|
||||
} else if (!props.immediate && !unref(isFirstLoaded)) {
|
||||
await fetch();
|
||||
// 动态搜索查询时,允许控制初始不加载数据
|
||||
if (!(!!props.apiSearch && !!props.apiSearch.show && !props.apiSearch.emptySearch)) {
|
||||
await fetch();
|
||||
} else {
|
||||
optionsRef.value = [];
|
||||
emitChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let debounceSearchFn = useDebounceFn(handleSearch, 500);
|
||||
|
||||
async function handleSearch(value: any) {
|
||||
if (!props.apiSearch) {
|
||||
return;
|
||||
}
|
||||
const { show, searchName, beforeFetch, interceptFetch } = props.apiSearch;
|
||||
if (!show || !searchName) {
|
||||
return;
|
||||
}
|
||||
|
||||
value = value || undefined;
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
value = (await beforeFetch(value)) || value;
|
||||
}
|
||||
|
||||
if (interceptFetch && isFunction(interceptFetch)) {
|
||||
if (!(await interceptFetch(value))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
searchParams.value = {
|
||||
[searchName]: value,
|
||||
};
|
||||
}
|
||||
|
||||
function emitChange() {
|
||||
emit('options-change', unref(getOptions));
|
||||
}
|
||||
|
@@ -32,7 +32,14 @@
|
||||
dataSource: { type: Array as PropType<Array<TransferItem>> },
|
||||
immediate: propTypes.bool.def(true),
|
||||
alwaysLoad: propTypes.bool.def(false),
|
||||
afterFetch: { type: Function },
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
resultField: propTypes.string.def(''),
|
||||
labelField: propTypes.string.def('title'),
|
||||
valueField: propTypes.string.def('key'),
|
||||
@@ -98,23 +105,29 @@
|
||||
);
|
||||
|
||||
async function fetch() {
|
||||
const api = props.api;
|
||||
let { api, beforeFetch, afterFetch, params, resultField, dataSource } = props;
|
||||
if (!api || !isFunction(api)) {
|
||||
if (Array.isArray(props.dataSource)) {
|
||||
_dataSource.value = props.dataSource;
|
||||
if (Array.isArray(dataSource)) {
|
||||
_dataSource.value = dataSource;
|
||||
}
|
||||
return;
|
||||
}
|
||||
_dataSource.value = [];
|
||||
try {
|
||||
const res = await api(props.params);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
params = (await beforeFetch(params)) || params;
|
||||
}
|
||||
let res = await api(params);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
if (Array.isArray(res)) {
|
||||
_dataSource.value = res;
|
||||
emitChange();
|
||||
return;
|
||||
}
|
||||
if (props.resultField) {
|
||||
_dataSource.value = get(res, props.resultField) || [];
|
||||
if (resultField) {
|
||||
_dataSource.value = get(res, resultField) || [];
|
||||
}
|
||||
emitChange();
|
||||
} catch (error) {
|
||||
|
@@ -7,10 +7,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { type Recordable, type AnyFunction } from '@vben/types';
|
||||
import { type Recordable } from '@vben/types';
|
||||
import { type PropType, computed, watch, ref, onMounted, unref, useAttrs } from 'vue';
|
||||
import { Tree, TreeProps } from 'ant-design-vue';
|
||||
import { isArray, isFunction } from '@/utils/is';
|
||||
import { isFunction } from '@/utils/is';
|
||||
import { get } from 'lodash-es';
|
||||
import { DataNode } from 'ant-design-vue/es/tree';
|
||||
import { useRuleFormItem } from '@/hooks/component/useFormItem';
|
||||
@@ -22,7 +22,14 @@
|
||||
params: { type: Object },
|
||||
immediate: { type: Boolean, default: true },
|
||||
resultField: { type: String, default: '' },
|
||||
afterFetch: { type: Function as PropType<AnyFunction> },
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
value: {
|
||||
type: Array as PropType<TreeProps['selectedKeys']>,
|
||||
},
|
||||
@@ -72,25 +79,28 @@
|
||||
});
|
||||
|
||||
async function fetch() {
|
||||
const { api, afterFetch } = props;
|
||||
let { api, beforeFetch, afterFetch, params, resultField } = props;
|
||||
if (!api || !isFunction(api)) return;
|
||||
loading.value = true;
|
||||
treeData.value = [];
|
||||
let result;
|
||||
let res;
|
||||
try {
|
||||
result = await api(props.params);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
params = (await beforeFetch(params)) || params;
|
||||
}
|
||||
res = await api(params);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
result = afterFetch(result);
|
||||
}
|
||||
loading.value = false;
|
||||
if (!result) return;
|
||||
if (!isArray(result)) {
|
||||
result = get(result, props.resultField);
|
||||
if (!res) return;
|
||||
if (resultField) {
|
||||
res = get(res, resultField) || [];
|
||||
}
|
||||
treeData.value = (result as (Recordable & { key: string | number })[]) || [];
|
||||
treeData.value = (res as (Recordable & { key: string | number })[]) || [];
|
||||
isFirstLoaded.value = true;
|
||||
emit('options-change', treeData.value);
|
||||
}
|
||||
|
@@ -34,6 +34,14 @@
|
||||
labelField: propTypes.string.def('title'),
|
||||
valueField: propTypes.string.def('value'),
|
||||
childrenField: propTypes.string.def('children'),
|
||||
beforeFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
afterFetch: {
|
||||
type: Function as PropType<Fn>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['options-change', 'change', 'load-data']);
|
||||
@@ -88,22 +96,28 @@
|
||||
}
|
||||
|
||||
async function fetch() {
|
||||
const { api } = props;
|
||||
let { api, beforeFetch, afterFetch, params, resultField } = props;
|
||||
if (!api || !isFunction(api) || loading.value) return;
|
||||
loading.value = true;
|
||||
treeData.value = [];
|
||||
let result;
|
||||
let res;
|
||||
try {
|
||||
result = await api(props.params);
|
||||
if (beforeFetch && isFunction(beforeFetch)) {
|
||||
params = (await beforeFetch(params)) || params;
|
||||
}
|
||||
res = await api(params);
|
||||
if (afterFetch && isFunction(afterFetch)) {
|
||||
res = (await afterFetch(res)) || res;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
loading.value = false;
|
||||
if (!result) return;
|
||||
if (!isArray(result)) {
|
||||
result = get(result, props.resultField);
|
||||
if (!res) return;
|
||||
if (resultField) {
|
||||
res = get(res, resultField) || [];
|
||||
}
|
||||
treeData.value = (result as Recordable<any>[]) || [];
|
||||
treeData.value = (res as Recordable<any>[]) || [];
|
||||
isFirstLoaded.value = true;
|
||||
emit('options-change', treeData.value);
|
||||
}
|
||||
|
@@ -277,6 +277,7 @@
|
||||
field,
|
||||
changeEvent = 'change',
|
||||
valueField,
|
||||
valueFormat,
|
||||
} = props.schema;
|
||||
|
||||
const isCheck = component && ['Switch', 'Checkbox'].includes(component);
|
||||
@@ -288,7 +289,10 @@
|
||||
const [e] = args;
|
||||
|
||||
const target = e ? e.target : null;
|
||||
const value = target ? (isCheck ? target.checked : target.value) : e;
|
||||
let value = target ? (isCheck ? target.checked : target.value) : e;
|
||||
if (isFunction(valueFormat)) {
|
||||
value = valueFormat({ ...unref(getValues), value });
|
||||
}
|
||||
props.setFormModel(field, value, props.schema);
|
||||
|
||||
if (propsData[eventKey]) {
|
||||
@@ -367,7 +371,7 @@
|
||||
}
|
||||
|
||||
function renderItem() {
|
||||
const { itemProps, slot, render, field, suffix, component } = props.schema;
|
||||
const { itemProps, slot, render, field, suffix, component, prefix } = props.schema;
|
||||
const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
|
||||
const { colon } = props.formProps;
|
||||
const opts = { disabled: unref(getDisable), readonly: unref(getReadonly) };
|
||||
@@ -383,7 +387,10 @@
|
||||
labelCol={labelCol}
|
||||
wrapperCol={wrapperCol}
|
||||
name={field}
|
||||
class={{ 'suffix-item': !!suffix }}
|
||||
class={{
|
||||
'suffix-item': !!suffix,
|
||||
'prefix-item': !!prefix,
|
||||
}}
|
||||
>
|
||||
<BasicTitle {...unref(getComponentsProps)}>{renderLabelHelpMessage()}</BasicTitle>
|
||||
</Form.Item>
|
||||
@@ -400,6 +407,8 @@
|
||||
const showSuffix = !!suffix;
|
||||
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
|
||||
|
||||
const showPrefix = !!prefix;
|
||||
const getPrefix = isFunction(prefix) ? prefix(unref(getValues)) : prefix;
|
||||
// TODO 自定义组件验证会出现问题,因此这里框架默认将自定义组件设置手动触发验证,如果其他组件还有此问题请手动设置autoLink=false
|
||||
if (component && NO_AUTO_LINK_COMPONENTS.includes(component)) {
|
||||
props.schema &&
|
||||
@@ -413,7 +422,10 @@
|
||||
<Form.Item
|
||||
name={field}
|
||||
colon={colon}
|
||||
class={{ 'suffix-item': showSuffix }}
|
||||
class={{
|
||||
'suffix-item': showSuffix,
|
||||
'prefix-item': showPrefix,
|
||||
}}
|
||||
{...(itemProps as Recordable<any>)}
|
||||
label={renderLabelHelpMessage()}
|
||||
rules={handleRules()}
|
||||
@@ -421,6 +433,7 @@
|
||||
wrapperCol={wrapperCol}
|
||||
>
|
||||
<div style="display:flex">
|
||||
{showPrefix && <span class="prefix">{getPrefix}</span>}
|
||||
<div style="flex:1;">{getContent()}</div>
|
||||
{showSuffix && <span class="suffix">{getSuffix}</span>}
|
||||
</div>
|
||||
|
@@ -2,7 +2,7 @@ import type { Rule as ValidationRule } from 'ant-design-vue/lib/form/interface';
|
||||
import type { ComponentType } from './types';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { dateUtil } from '@/utils/dateUtil';
|
||||
import { isNumber, isObject } from '@/utils/is';
|
||||
import { isObject } from '@/utils/is';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -31,8 +31,13 @@ export function createPlaceholderMessage(component: ComponentType) {
|
||||
|
||||
const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'];
|
||||
|
||||
/**
|
||||
* 上传组件
|
||||
*/
|
||||
export const uploadItemType: ComponentType[] = ['Upload', 'ImageUpload'];
|
||||
|
||||
function genType() {
|
||||
return [...DATE_TYPE, 'RangePicker'];
|
||||
return [...DATE_TYPE, 'RangePicker', 'TimeRangePicker'];
|
||||
}
|
||||
|
||||
export function setComponentRuleType(
|
||||
@@ -45,7 +50,7 @@ export function setComponentRuleType(
|
||||
}
|
||||
if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) {
|
||||
rule.type = valueFormat ? 'string' : 'object';
|
||||
} else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) {
|
||||
} else if (['RangePicker', 'CheckboxGroup'].includes(component)) {
|
||||
rule.type = 'array';
|
||||
} else if (['InputNumber'].includes(component)) {
|
||||
rule.type = 'number';
|
||||
@@ -69,14 +74,6 @@ export const defaultValueComponents = [
|
||||
'InputTextArea',
|
||||
];
|
||||
|
||||
export function handleInputNumberValue(component?: ComponentType, val?: any) {
|
||||
if (!component) return val;
|
||||
if (defaultValueComponents.includes(component)) {
|
||||
return val && isNumber(val) ? `${val}` : val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间字段
|
||||
*/
|
||||
|
@@ -1,6 +1,15 @@
|
||||
import type { ColEx } from '../types';
|
||||
import type { AdvanceState } from '../types/hooks';
|
||||
import { ComputedRef, getCurrentInstance, Ref, shallowReactive, computed, unref, watch } from 'vue';
|
||||
import {
|
||||
ComputedRef,
|
||||
getCurrentInstance,
|
||||
Ref,
|
||||
shallowReactive,
|
||||
computed,
|
||||
unref,
|
||||
watch,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form';
|
||||
import { isBoolean, isFunction, isNumber, isObject } from '@/utils/is';
|
||||
import { useBreakpoint } from '@/hooks/event/useBreakpoint';
|
||||
@@ -49,14 +58,17 @@ export default function ({
|
||||
return 0;
|
||||
});
|
||||
|
||||
const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30);
|
||||
// const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30);
|
||||
|
||||
watch(
|
||||
[() => unref(getSchema), () => advanceState.isAdvanced, () => unref(realWidthRef)],
|
||||
() => {
|
||||
const { showAdvancedButton } = unref(getProps);
|
||||
if (showAdvancedButton) {
|
||||
debounceUpdateAdvanced();
|
||||
// debounceUpdateAdvanced();
|
||||
nextTick(() => {
|
||||
updateAdvanced();
|
||||
});
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
@@ -120,24 +132,18 @@ export default function ({
|
||||
const { baseColProps = {} } = unref(getProps);
|
||||
|
||||
for (const schema of unref(getSchema)) {
|
||||
const { show, colProps } = schema;
|
||||
const { show, ifShow, colProps } = schema;
|
||||
const renderCallbackParams = {
|
||||
schema: schema,
|
||||
model: formModel,
|
||||
field: schema.field,
|
||||
values: { ...unref(defaultValueRef), ...formModel },
|
||||
};
|
||||
let isShow = true;
|
||||
|
||||
if (isBoolean(show)) {
|
||||
isShow = show;
|
||||
}
|
||||
|
||||
if (isFunction(show)) {
|
||||
isShow = show({
|
||||
schema: schema,
|
||||
model: formModel,
|
||||
field: schema.field,
|
||||
values: {
|
||||
...unref(defaultValueRef),
|
||||
...formModel,
|
||||
},
|
||||
});
|
||||
}
|
||||
isShow && isBoolean(ifShow) && (isShow = ifShow);
|
||||
isShow && isFunction(ifShow) && (isShow = ifShow(renderCallbackParams));
|
||||
isShow && isBoolean(show) && (isShow = show);
|
||||
isShow && isFunction(show) && (isShow = show(renderCallbackParams));
|
||||
|
||||
if (isShow && (colProps || baseColProps)) {
|
||||
const { itemColSum: sum, isAdvanced } = getAdvanced(
|
||||
|
@@ -78,9 +78,13 @@ export function useForm(props?: Props): UseFormReturnType {
|
||||
form.clearValidate(name);
|
||||
},
|
||||
|
||||
resetFields: async () => {
|
||||
getForm().then(async (form) => {
|
||||
await form.resetFields();
|
||||
resetFields: () => {
|
||||
// 修复表单重置后,页面变化了,但是由于异步问题导致表单内部的状态没有及时同步
|
||||
return new Promise((resolve) => {
|
||||
getForm().then(async (form) => {
|
||||
await form.resetFields();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -121,6 +125,9 @@ export function useForm(props?: Props): UseFormReturnType {
|
||||
const form = await getForm();
|
||||
return form.validateFields(nameList);
|
||||
},
|
||||
resetDefaultField: async (nameList?: NamePath[]) => {
|
||||
unref(formRef)?.resetDefaultField(nameList);
|
||||
},
|
||||
};
|
||||
|
||||
return [register, methods];
|
||||
|
@@ -2,17 +2,18 @@ import type { ComputedRef, Ref } from 'vue';
|
||||
import type { FormProps, FormSchemaInner as FormSchema, FormActionType } from '../types/form';
|
||||
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
||||
import { unref, toRaw, nextTick } from 'vue';
|
||||
import { isArray, isFunction, isObject, isString, isDef, isNil } from '@/utils/is';
|
||||
import { isArray, isFunction, isObject, isString, isNil } from '@/utils/is';
|
||||
import { deepMerge } from '@/utils';
|
||||
import {
|
||||
dateItemType,
|
||||
handleInputNumberValue,
|
||||
defaultValueComponents,
|
||||
isIncludeSimpleComponents,
|
||||
uploadItemType,
|
||||
} from '../helper';
|
||||
import { dateUtil } from '@/utils/dateUtil';
|
||||
import { cloneDeep, set, uniqBy, get } from 'lodash-es';
|
||||
import { cloneDeep, has, uniqBy, get, set } from 'lodash-es';
|
||||
import { error } from '@/utils/log';
|
||||
import { ComponentProps } from '../types';
|
||||
|
||||
interface UseFormActionContext {
|
||||
emit: EmitType;
|
||||
@@ -24,7 +25,12 @@ interface UseFormActionContext {
|
||||
schemaRef: Ref<FormSchema[]>;
|
||||
handleFormValues: Fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Is it upload
|
||||
*/
|
||||
export function itemIsUploadComponent(key: keyof ComponentProps) {
|
||||
return uploadItemType.includes(key);
|
||||
}
|
||||
function tryConstructArray(field: string, values: Recordable = {}): any[] | undefined {
|
||||
const pattern = /^\[(.+)\]$/;
|
||||
if (pattern.test(field)) {
|
||||
@@ -34,37 +40,14 @@ function tryConstructArray(field: string, values: Recordable = {}): any[] | unde
|
||||
if (!keys.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = [];
|
||||
keys.forEach((k, index) => {
|
||||
set(result, index, values[k.trim()]);
|
||||
});
|
||||
|
||||
return result.filter(Boolean).length ? result : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tryConstructObject(field: string, values: Recordable = {}): Recordable | undefined {
|
||||
const pattern = /^\{(.+)\}$/;
|
||||
if (pattern.test(field)) {
|
||||
const match = field.match(pattern);
|
||||
if (match && match[1]) {
|
||||
const keys = match[1].split(',');
|
||||
if (!keys.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = {};
|
||||
keys.forEach((k) => {
|
||||
set(result, k.trim(), values[k.trim()]);
|
||||
});
|
||||
|
||||
return Object.values(result).filter(Boolean).length ? result : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function useFormEvents({
|
||||
emit,
|
||||
getProps,
|
||||
@@ -114,17 +97,11 @@ export function useFormEvents({
|
||||
|
||||
const fields = getAllFields();
|
||||
|
||||
// key 支持 a.b.c 的嵌套写法
|
||||
const delimiter = '.';
|
||||
const nestKeyArray = fields.filter((item) => String(item).indexOf(delimiter) >= 0);
|
||||
|
||||
const validKeys: string[] = [];
|
||||
fields.forEach((key) => {
|
||||
const schema = unref(getSchema).find((item) => item.field === key);
|
||||
let value = get(values, key);
|
||||
const hasKey = Reflect.has(values, key);
|
||||
|
||||
value = handleInputNumberValue(schema?.component, value);
|
||||
const value = get(values, key);
|
||||
const hasKey = has(values, key);
|
||||
const { componentProps } = schema || {};
|
||||
let _props = componentProps as any;
|
||||
if (typeof componentProps === 'function') {
|
||||
@@ -134,47 +111,79 @@ export function useFormEvents({
|
||||
});
|
||||
}
|
||||
|
||||
const constructValue = tryConstructArray(key, values) || tryConstructObject(key, values);
|
||||
let constructValue;
|
||||
const setDateFieldValue = (v) => {
|
||||
return v ? (_props?.valueFormat ? v : dateUtil(v)) : null;
|
||||
};
|
||||
|
||||
// 0| '' is allow
|
||||
if (hasKey || !!constructValue) {
|
||||
const fieldValue = constructValue || value;
|
||||
// time type
|
||||
if (itemIsDateType(key)) {
|
||||
// Adapt date component
|
||||
if (itemIsDateComponent(schema?.component)) {
|
||||
constructValue = tryConstructArray(key, values);
|
||||
if (constructValue) {
|
||||
const fieldValue = constructValue || value;
|
||||
if (Array.isArray(fieldValue)) {
|
||||
const arr: any[] = [];
|
||||
for (const ele of fieldValue) {
|
||||
arr.push(setDateFieldValue(ele));
|
||||
}
|
||||
unref(formModel)[key] = arr;
|
||||
validKeys.push(key);
|
||||
} else {
|
||||
unref(formModel)[key] = setDateFieldValue(fieldValue);
|
||||
validKeys.push(key);
|
||||
}
|
||||
} else {
|
||||
unref(formModel)[key] = fieldValue;
|
||||
}
|
||||
}
|
||||
// Adapt upload component
|
||||
if (itemIsUploadComponent(schema?.component)) {
|
||||
constructValue = get(value, key);
|
||||
const fieldValue = constructValue || value;
|
||||
if (fieldValue) {
|
||||
if (isArray(fieldValue)) {
|
||||
unref(formModel)[key] = fieldValue;
|
||||
} else if (typeof fieldValue == 'string') {
|
||||
unref(formModel)[key] = [fieldValue];
|
||||
}
|
||||
}
|
||||
validKeys.push(key);
|
||||
return;
|
||||
}
|
||||
// Adapt common component
|
||||
if (hasKey) {
|
||||
constructValue = get(value, key);
|
||||
const fieldValue = constructValue || value;
|
||||
unref(formModel)[key] = fieldValue;
|
||||
if (_props?.onChange) {
|
||||
_props?.onChange(fieldValue);
|
||||
}
|
||||
validKeys.push(key);
|
||||
} else {
|
||||
nestKeyArray.forEach((nestKey: string) => {
|
||||
try {
|
||||
const value = get(values,nestKey)
|
||||
if (isDef(value)) {
|
||||
unref(formModel)[nestKey] = unref(value);
|
||||
validKeys.push(nestKey);
|
||||
}
|
||||
} catch (e) {
|
||||
// key not exist
|
||||
if (isDef(defaultValueRef.value[nestKey])) {
|
||||
unref(formModel)[nestKey] = cloneDeep(unref(defaultValueRef.value[nestKey]));
|
||||
}
|
||||
}
|
||||
});
|
||||
// key not exist
|
||||
// refer:https://github.com/vbenjs/vue-vben-admin/issues/3795
|
||||
}
|
||||
});
|
||||
validateFields(validKeys).catch((_) => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Set form default value
|
||||
*/
|
||||
function resetDefaultField(nameList?: NamePath[]) {
|
||||
if (!Array.isArray(nameList)) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(nameList) && nameList.length === 0) {
|
||||
return;
|
||||
}
|
||||
const validKeys: string[] = [];
|
||||
const keys = Object.keys(unref(formModel));
|
||||
if (!keys) {
|
||||
return;
|
||||
}
|
||||
nameList.forEach((key: any) => {
|
||||
if (keys.includes(key)) {
|
||||
validKeys.push(key);
|
||||
unref(formModel)[key] = cloneDeep(unref(get(defaultValueRef.value, key)));
|
||||
}
|
||||
});
|
||||
validateFields(validKeys).catch((_) => {});
|
||||
@@ -189,9 +198,9 @@ export function useFormEvents({
|
||||
return;
|
||||
}
|
||||
|
||||
let fieldList: string[] = isString(fields) ? [fields] : fields;
|
||||
let fieldList = (isString(fields) ? [fields] : fields) as string[];
|
||||
if (isString(fields)) {
|
||||
fieldList = [fields];
|
||||
fieldList = [fields as string];
|
||||
}
|
||||
for (const field of fieldList) {
|
||||
_removeSchemaByField(field, schemaList);
|
||||
@@ -334,10 +343,8 @@ export function useFormEvents({
|
||||
/**
|
||||
* @description: Is it time
|
||||
*/
|
||||
function itemIsDateType(key: string) {
|
||||
return unref(getSchema).some((item) => {
|
||||
return item.field === key && item.component ? dateItemType.includes(item.component) : false;
|
||||
});
|
||||
function itemIsDateComponent(key: string) {
|
||||
return dateItemType.includes(key);
|
||||
}
|
||||
|
||||
async function validateFields(nameList?: NamePath[] | undefined) {
|
||||
@@ -420,6 +427,7 @@ export function useFormEvents({
|
||||
resetFields,
|
||||
setFieldsValue,
|
||||
scrollToField,
|
||||
resetDefaultField,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -431,7 +439,7 @@ function getDefaultValue(
|
||||
let defaultValue = cloneDeep(defaultValueRef.value[key]);
|
||||
const isInput = checkIsInput(schema);
|
||||
if (isInput) {
|
||||
return defaultValue || undefined;
|
||||
return !isNil(defaultValue) ? defaultValue : undefined;
|
||||
}
|
||||
if (!defaultValue && schema && checkIsRangeSlider(schema)) {
|
||||
defaultValue = [0, 0];
|
||||
|
@@ -135,7 +135,7 @@ export function useFormValues({
|
||||
const schemas = unref(getSchema);
|
||||
const obj: Recordable = {};
|
||||
schemas.forEach((item) => {
|
||||
const { defaultValue, defaultValueObj } = item;
|
||||
const { defaultValue, defaultValueObj, componentProps = {} } = item;
|
||||
const fieldKeys = Object.keys(defaultValueObj || {});
|
||||
if (fieldKeys.length) {
|
||||
fieldKeys.forEach((field) => {
|
||||
@@ -152,6 +152,12 @@ export function useFormValues({
|
||||
formModel[item.field] = defaultValue;
|
||||
}
|
||||
}
|
||||
if (!isNil(componentProps?.defaultValue)) {
|
||||
obj[item.field] = componentProps?.defaultValue;
|
||||
if (formModel[item.field] === undefined) {
|
||||
formModel[item.field] = componentProps?.defaultValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
defaultValueRef.value = cloneDeep(obj);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import type { Ref } from 'vue';
|
||||
import { computed, unref } from 'vue';
|
||||
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form';
|
||||
import { isNumber } from '@/utils/is';
|
||||
import { isDef, isNumber } from '@/utils/is';
|
||||
|
||||
export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
|
||||
return computed(() => {
|
||||
@@ -23,11 +23,11 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
|
||||
};
|
||||
return { labelCol, wrapperCol };
|
||||
}
|
||||
let width = labelWidth || globalLabelWidth;
|
||||
let width = labelWidth ?? globalLabelWidth;
|
||||
const col = { ...globalLabelCol, ...labelCol };
|
||||
const wrapCol = { ...globWrapperCol, ...wrapperCol };
|
||||
|
||||
if (width) {
|
||||
if (isDef(width)) {
|
||||
width = isNumber(width) ? `${width}px` : width;
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,7 @@ export interface FormActionType {
|
||||
validateFields: (nameList?: NamePath[]) => Promise<any>;
|
||||
validate: <T = Recordable>(nameList?: NamePath[] | false) => Promise<T>;
|
||||
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>;
|
||||
resetDefaultField: (name?: NamePath[]) => void;
|
||||
}
|
||||
|
||||
export type RegisterFn = (formInstance: FormActionType) => void;
|
||||
@@ -166,8 +167,16 @@ interface BaseFormSchema<T extends ComponentType = any> {
|
||||
// Required
|
||||
required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
||||
|
||||
suffix?: string | number | ((values: RenderCallbackParams) => string | number);
|
||||
|
||||
suffix?:
|
||||
| string
|
||||
| number
|
||||
| VNode
|
||||
| ((renderCallbackParams: RenderCallbackParams) => string | VNode | number);
|
||||
prefix?:
|
||||
| string
|
||||
| number
|
||||
| VNode
|
||||
| ((renderCallbackParams: RenderCallbackParams) => string | VNode | number);
|
||||
// Validation rules
|
||||
rules?: Rule[];
|
||||
// Check whether the information is added to the label
|
||||
@@ -188,6 +197,9 @@ interface BaseFormSchema<T extends ComponentType = any> {
|
||||
// 是否自动处理与时间相关组件的默认值
|
||||
isHandleDateDefaultValue?: boolean;
|
||||
|
||||
// 是否使用valueFormat自动处理默认值
|
||||
isHandleDefaultValue?: boolean;
|
||||
|
||||
isAdvanced?: boolean;
|
||||
|
||||
// Matching details components
|
||||
@@ -223,6 +235,8 @@ interface BaseFormSchema<T extends ComponentType = any> {
|
||||
dynamicReadonly?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
||||
|
||||
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
|
||||
|
||||
valueFormat?: (arg: Partial<RenderCallbackParams> & { value: any }) => any;
|
||||
}
|
||||
export interface ComponentFormSchema<T extends ComponentType = any> extends BaseFormSchema<T> {
|
||||
// render component
|
||||
|
@@ -54,7 +54,7 @@
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgb(240 242 245 / 40%);
|
||||
background-color: #f0f2f566;
|
||||
|
||||
&.absolute {
|
||||
position: absolute;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VNode, defineComponent, createVNode, render, reactive, h } from 'vue';
|
||||
import { createVNode, defineComponent, h, reactive, render, VNode } from 'vue';
|
||||
import type { LoadingProps } from './typing';
|
||||
|
||||
import Loading from './Loading.vue';
|
||||
@@ -19,13 +19,13 @@ export function createLoading(props?: Partial<LoadingProps>, target?: HTMLElemen
|
||||
|
||||
vm = createVNode(LoadingWrap);
|
||||
|
||||
let container: Nullable<HTMLElement> = null;
|
||||
if (wait) {
|
||||
// TODO fix https://github.com/anncwb/vue-vben-admin/issues/438
|
||||
setTimeout(() => {
|
||||
render(vm, document.createElement('div'));
|
||||
render(vm, (container = document.createElement('div')));
|
||||
}, 0);
|
||||
} else {
|
||||
render(vm, document.createElement('div'));
|
||||
render(vm, (container = document.createElement('div')));
|
||||
}
|
||||
|
||||
function close() {
|
||||
@@ -41,6 +41,11 @@ export function createLoading(props?: Partial<LoadingProps>, target?: HTMLElemen
|
||||
target.appendChild(vm.el as HTMLElement);
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
container && render(null, container);
|
||||
container = vm = null;
|
||||
}
|
||||
|
||||
if (target) {
|
||||
open(target);
|
||||
}
|
||||
@@ -48,6 +53,7 @@ export function createLoading(props?: Partial<LoadingProps>, target?: HTMLElemen
|
||||
vm,
|
||||
close,
|
||||
open,
|
||||
destroy,
|
||||
setTip: (tip: string) => {
|
||||
data.tip = tip;
|
||||
},
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import type { Ref } from 'vue';
|
||||
import { unref } from 'vue';
|
||||
import { tryOnUnmounted } from '@vueuse/core';
|
||||
import { createLoading } from './createLoading';
|
||||
import type { LoadingProps } from './typing';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
export interface UseLoadingOptions {
|
||||
target?: any;
|
||||
@@ -45,5 +46,9 @@ export function useLoading(
|
||||
instance.setTip(tip);
|
||||
};
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
instance.destroy();
|
||||
});
|
||||
|
||||
return [open, close, setTip];
|
||||
}
|
||||
|
@@ -127,7 +127,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-height: 600px) {
|
||||
.ant-modal {
|
||||
top: 60px;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import type { Options, Props } from './typing';
|
||||
import ImgPreview from './Functional.vue';
|
||||
import { isClient } from '@/utils/is';
|
||||
import { createVNode, render } from 'vue';
|
||||
import ImgPreview from './Functional.vue';
|
||||
import type { Options, Props } from './typing';
|
||||
|
||||
let instance: ReturnType<typeof createVNode> | null = null;
|
||||
export function createImgPreview(options: Options) {
|
||||
@@ -10,8 +10,13 @@ export function createImgPreview(options: Options) {
|
||||
const container = document.createElement('div');
|
||||
Object.assign(propsData, { show: true, index: 0, scaleStep: 100 }, options);
|
||||
|
||||
instance = createVNode(ImgPreview, propsData);
|
||||
render(instance, container);
|
||||
document.body.appendChild(container);
|
||||
if (instance?.component) {
|
||||
// 存在实例时,更新props
|
||||
Object.assign(instance.component.props, propsData);
|
||||
} else {
|
||||
instance = createVNode(ImgPreview, propsData);
|
||||
render(instance, container);
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
return instance.component?.exposed;
|
||||
}
|
||||
|
@@ -153,11 +153,11 @@
|
||||
height: 0;
|
||||
transition: 0.3s background-color;
|
||||
border-radius: inherit;
|
||||
background-color: rgb(144 147 153 / 30%);
|
||||
background-color: #9093994d;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(144 147 153 / 50%);
|
||||
background-color: #90939980;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,11 +17,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType, ref, computed, unref, getCurrentInstance, watch, useSlots } from 'vue';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { computed, getCurrentInstance, PropType, ref, unref, useSlots, watch } from 'vue';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
|
||||
defineOptions({ name: 'MenuItem' });
|
||||
@@ -76,7 +76,7 @@
|
||||
const { uidList } = getParentList();
|
||||
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
opened: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList,
|
||||
});
|
||||
|
@@ -57,27 +57,27 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { type TimeoutHandle, type Recordable } from '@vben/types';
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import {
|
||||
computed,
|
||||
unref,
|
||||
getCurrentInstance,
|
||||
reactive,
|
||||
provide,
|
||||
onBeforeMount,
|
||||
inject,
|
||||
} from 'vue';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
import { CollapseTransition } from '@/components/Transition';
|
||||
import Icon from '@/components/Icon/Icon.vue';
|
||||
import { Popover } from 'ant-design-vue';
|
||||
import { CollapseTransition } from '@/components/Transition';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
import { isBoolean, isObject } from '@/utils/is';
|
||||
import { mitt } from '@/utils/mitt';
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { type Recordable, type TimeoutHandle } from '@vben/types';
|
||||
import { Popover } from 'ant-design-vue';
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import {
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
inject,
|
||||
onBeforeMount,
|
||||
provide,
|
||||
reactive,
|
||||
unref,
|
||||
} from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
|
||||
defineOptions({ name: 'SubMenu' });
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
if (unref(getAccordion)) {
|
||||
const { uidList } = getParentList();
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
opened: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList,
|
||||
});
|
||||
@@ -267,9 +267,9 @@
|
||||
return;
|
||||
}
|
||||
if (isObject(data) && rootProps.accordion) {
|
||||
const { opend, parent, uidList } = data as Recordable<any>;
|
||||
const { opened, parent, uidList } = data as Recordable<any>;
|
||||
if (parent === instance?.parent) {
|
||||
state.opened = opend;
|
||||
state.opened = opened;
|
||||
} else if (!uidList.includes(instance?.uid)) {
|
||||
state.opened = false;
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import type { InjectionKey, Ref, ComponentInternalInstance } from 'vue';
|
||||
import type { Emitter } from '@/utils/mitt';
|
||||
import { createContext, useContext } from '@/hooks/core/useContext';
|
||||
import type { Emitter } from '@/utils/mitt';
|
||||
import type { ComponentInternalInstance, InjectionKey, Ref } from 'vue';
|
||||
|
||||
export type MenuEmitterEvents = {
|
||||
'on-update-opened':
|
||||
| (string | number)[]
|
||||
| {
|
||||
opend: boolean;
|
||||
opened: boolean;
|
||||
parent?: ComponentInternalInstance | null;
|
||||
uidList: number[];
|
||||
};
|
||||
|
@@ -32,13 +32,9 @@
|
||||
<HeaderCell :column="column" />
|
||||
</slot>
|
||||
</template>
|
||||
<!-- 增加对antdv3.x兼容 -->
|
||||
<template #bodyCell="data">
|
||||
<slot name="bodyCell" v-bind="data || {}"></slot>
|
||||
</template>
|
||||
<!-- <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">-->
|
||||
<!-- <HeaderCell :column="column" />-->
|
||||
<!-- </template>-->
|
||||
</Table>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -17,6 +17,7 @@
|
||||
import { treeToList } from '@/utils/helper/treeHelper';
|
||||
import { Spin } from 'ant-design-vue';
|
||||
import { parseRowKey } from '../../helper';
|
||||
import { warn } from '@/utils/log';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'EditableCell',
|
||||
@@ -282,6 +283,7 @@
|
||||
});
|
||||
} catch (e) {
|
||||
result = false;
|
||||
warn(e);
|
||||
} finally {
|
||||
spinning.value = false;
|
||||
}
|
||||
@@ -369,11 +371,9 @@
|
||||
if (!props.record.editValueRefs) props.record.editValueRefs = {};
|
||||
props.record.editValueRefs[props.column.dataIndex as any] = currentValueRef;
|
||||
}
|
||||
/* eslint-disable */
|
||||
props.record.onCancelEdit = () => {
|
||||
isArray(props.record?.cancelCbs) && props.record?.cancelCbs.forEach((fn) => fn());
|
||||
};
|
||||
/* eslint-disable */
|
||||
props.record.onSubmitEdit = async () => {
|
||||
if (isArray(props.record?.submitCbs)) {
|
||||
if (!props.record?.onValid?.()) return;
|
||||
@@ -508,7 +508,7 @@
|
||||
}
|
||||
.@{prefix-cls} {
|
||||
position: relative;
|
||||
min-height: 24px; //设置高度让其始终可被hover
|
||||
min-height: 24px; // 设置高度让其始终可被hover
|
||||
|
||||
&__wrapper {
|
||||
display: flex;
|
||||
|
@@ -540,13 +540,13 @@
|
||||
label:
|
||||
typeof col.title === 'string'
|
||||
? col.title
|
||||
: col.customTitle === 'string'
|
||||
: typeof col.customTitle === 'string'
|
||||
? col.customTitle
|
||||
: '',
|
||||
value:
|
||||
typeof col.dataIndex === 'string'
|
||||
? col.dataIndex
|
||||
: col.title === 'string'
|
||||
: typeof col.title === 'string'
|
||||
? col.title
|
||||
: '',
|
||||
column: {
|
||||
|
@@ -39,7 +39,7 @@
|
||||
redo: true,
|
||||
size: true,
|
||||
setting: true,
|
||||
settingCache: false,
|
||||
settingCache: !import.meta.env.DEV,
|
||||
fullScreen: false,
|
||||
...props.setting,
|
||||
};
|
||||
@@ -55,6 +55,8 @@
|
||||
</script>
|
||||
<style lang="less">
|
||||
.table-settings {
|
||||
display: flex;
|
||||
|
||||
& > * {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
@@ -114,32 +114,41 @@ export function useDataSource(
|
||||
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
||||
});
|
||||
|
||||
const getDataSourceRef = computed(() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
return unref(dataSourceRef);
|
||||
}
|
||||
if (unref(getAutoCreateKey)) {
|
||||
const firstItem = dataSource[0];
|
||||
const lastItem = dataSource[dataSource.length - 1];
|
||||
const getDataSourceRef: Ref<Recordable<any>[]> = ref([]);
|
||||
|
||||
if (firstItem && lastItem) {
|
||||
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
|
||||
const data = cloneDeep(unref(dataSourceRef));
|
||||
data.forEach((item) => {
|
||||
if (!item[ROW_KEY]) {
|
||||
item[ROW_KEY] = buildUUID();
|
||||
}
|
||||
if (item.children && item.children.length) {
|
||||
setTableKey(item.children);
|
||||
}
|
||||
});
|
||||
dataSourceRef.value = data;
|
||||
watch(
|
||||
() => dataSourceRef.value,
|
||||
() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
getDataSourceRef.value = unref(dataSourceRef);
|
||||
}
|
||||
if (unref(getAutoCreateKey)) {
|
||||
const firstItem = dataSource[0];
|
||||
const lastItem = dataSource[dataSource.length - 1];
|
||||
|
||||
if (firstItem && lastItem) {
|
||||
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
|
||||
const data = cloneDeep(unref(dataSourceRef));
|
||||
data.forEach((item) => {
|
||||
if (!item[ROW_KEY]) {
|
||||
item[ROW_KEY] = buildUUID();
|
||||
}
|
||||
if (item.children && item.children.length) {
|
||||
setTableKey(item.children);
|
||||
}
|
||||
});
|
||||
dataSourceRef.value = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return unref(dataSourceRef);
|
||||
});
|
||||
getDataSourceRef.value = unref(dataSourceRef);
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
async function updateTableData(index: number, key: Key, value: any) {
|
||||
const record = dataSourceRef.value[index];
|
||||
@@ -351,7 +360,7 @@ export function useDataSource(
|
||||
});
|
||||
|
||||
return {
|
||||
getDataSourceRef,
|
||||
getDataSourceRef: computed(() => getDataSourceRef.value),
|
||||
getDataSource,
|
||||
getRawDataSource,
|
||||
searchInfoRef,
|
||||
|
@@ -33,7 +33,7 @@ export function useRowSelection(
|
||||
// 点击 checkbox/radiobox 触发
|
||||
|
||||
// 取出【当前页】所有 keyValues
|
||||
const currentPageKeys = tableData.value.map((o) => parseRowKeyValue(unref(getRowKey), o));
|
||||
const currentPageKeys = getCcurrentPageKeys();
|
||||
|
||||
// 从【所有分页】已选的 keyValues,且属于【当前页】的部分
|
||||
for (const selectedKey of selectedRowKeysRef.value.filter((k) =>
|
||||
@@ -110,6 +110,18 @@ export function useRowSelection(
|
||||
const { rowKey } = unref(propsRef);
|
||||
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
||||
});
|
||||
function getCcurrentPageKeys() {
|
||||
const { childrenColumnName = 'children' } = unref(propsRef);
|
||||
const keys: Key[] = [];
|
||||
const extractKeys = (record: Recordable) => {
|
||||
keys.push(parseRowKeyValue(unref(getRowKey), record));
|
||||
if (record[childrenColumnName]?.length) {
|
||||
record[childrenColumnName].forEach(extractKeys);
|
||||
}
|
||||
};
|
||||
tableData.value.forEach(extractKeys);
|
||||
return keys;
|
||||
}
|
||||
|
||||
function setSelectedRowKeys(keyValues?: Key[]) {
|
||||
selectedRowKeysRef.value = keyValues || [];
|
||||
|
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<Space>
|
||||
<a-button type="primary" @click="openUploadModal" preIcon="carbon:cloud-upload">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="openUploadModal"
|
||||
preIcon="carbon:cloud-upload"
|
||||
:disabled="disabled"
|
||||
>
|
||||
{{ t('component.upload.upload') }}
|
||||
</a-button>
|
||||
<Tooltip placement="bottom" v-if="showPreview">
|
||||
@@ -31,6 +36,7 @@
|
||||
|
||||
<UploadPreviewModal
|
||||
:value="fileList"
|
||||
:max-number="bindValue.maxNumber"
|
||||
@register="registerPreviewModal"
|
||||
@list-change="handlePreviewChange"
|
||||
@delete="handlePreviewDelete"
|
||||
@@ -48,9 +54,11 @@
|
||||
import { uploadContainerProps } from './props';
|
||||
import { omit } from 'lodash-es';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { isArray } from '@/utils/is';
|
||||
import { isArray, isObject, isString } from '@/utils/is';
|
||||
import UploadModal from './components/UploadModal.vue';
|
||||
import UploadPreviewModal from './components/UploadPreviewModal.vue';
|
||||
import { BaseFileItem } from './types/typing';
|
||||
import { buildUUID } from '@/utils/uuid';
|
||||
|
||||
defineOptions({ name: 'BasicUpload' });
|
||||
|
||||
@@ -66,7 +74,7 @@
|
||||
// 预览modal
|
||||
const [registerPreviewModal, { openModal: openPreviewModal }] = useModal();
|
||||
|
||||
const fileList = ref<string[]>([]);
|
||||
const fileList = ref<BaseFileItem[] | any[]>([]);
|
||||
|
||||
const showPreview = computed(() => {
|
||||
const { emptyHidePreview } = props;
|
||||
@@ -79,26 +87,72 @@
|
||||
return omit(value, 'onChange');
|
||||
});
|
||||
|
||||
const isFirstRender = ref<boolean>(true);
|
||||
|
||||
function getValue(valueKey = 'url') {
|
||||
const list = (fileList.value || []).map((item: any) => {
|
||||
return item[valueKey];
|
||||
});
|
||||
return list;
|
||||
}
|
||||
function genFileListByUrls(urls: string[]) {
|
||||
const list = urls.map((e) => {
|
||||
return {
|
||||
uid: buildUUID(),
|
||||
url: e,
|
||||
};
|
||||
});
|
||||
return list;
|
||||
}
|
||||
watch(
|
||||
() => props.value,
|
||||
(value = []) => {
|
||||
fileList.value = isArray(value) ? value : [];
|
||||
(v = []) => {
|
||||
let values: string[] = [];
|
||||
if (v) {
|
||||
if (isArray(v)) {
|
||||
values = v;
|
||||
} else if (typeof v == 'string') {
|
||||
values.push(v);
|
||||
}
|
||||
fileList.value = values.map((item) => {
|
||||
if (item && isString(item)) {
|
||||
return {
|
||||
uid: buildUUID(),
|
||||
url: item,
|
||||
};
|
||||
} else if (item && isObject(item)) {
|
||||
return item;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}) as any;
|
||||
}
|
||||
emit('update:value', values);
|
||||
if (!isFirstRender.value) {
|
||||
emit('change', values);
|
||||
isFirstRender.value = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// 上传modal保存操作
|
||||
function handleChange(urls: string[]) {
|
||||
fileList.value = [...unref(fileList), ...(urls || [])];
|
||||
emit('update:value', fileList.value);
|
||||
emit('change', fileList.value);
|
||||
function handleChange(urls: string[], valueKey: string) {
|
||||
fileList.value = [...unref(fileList), ...(genFileListByUrls(urls) || [])];
|
||||
const values = getValue(valueKey);
|
||||
emit('update:value', values);
|
||||
emit('change', values);
|
||||
}
|
||||
|
||||
// 预览modal保存操作
|
||||
function handlePreviewChange(urls: string[]) {
|
||||
fileList.value = [...(urls || [])];
|
||||
emit('update:value', fileList.value);
|
||||
emit('change', fileList.value);
|
||||
function handlePreviewChange(fileItems: string[], valueKey: string) {
|
||||
fileList.value = [...(fileItems || [])];
|
||||
const values = getValue(valueKey);
|
||||
emit('update:value', values);
|
||||
emit('change', values);
|
||||
}
|
||||
|
||||
function handleDelete(record: Recordable<any>) {
|
||||
|
@@ -9,6 +9,7 @@
|
||||
:maxCount="maxNumber"
|
||||
:before-upload="beforeUpload"
|
||||
:custom-request="customRequest"
|
||||
:disabled="disabled"
|
||||
@preview="handlePreview"
|
||||
@remove="handleRemove"
|
||||
>
|
||||
@@ -62,6 +63,7 @@
|
||||
const fileList = ref<UploadProps['fileList']>([]);
|
||||
const isLtMsg = ref<boolean>(true);
|
||||
const isActMsg = ref<boolean>(true);
|
||||
const isFirstRender = ref<boolean>(true);
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
@@ -70,8 +72,8 @@
|
||||
isInnerOperate.value = false;
|
||||
return;
|
||||
}
|
||||
let value: string[] = [];
|
||||
if (v) {
|
||||
let value: string[] = [];
|
||||
if (isArray(v)) {
|
||||
value = v;
|
||||
} else {
|
||||
@@ -92,6 +94,11 @@
|
||||
}
|
||||
}) as UploadProps['fileList'];
|
||||
}
|
||||
emit('update:value', value);
|
||||
if (!isFirstRender.value) {
|
||||
emit('change', value);
|
||||
isFirstRender.value = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
@@ -157,21 +164,22 @@
|
||||
};
|
||||
|
||||
async function customRequest(info: UploadRequestOption<any>) {
|
||||
const { api } = props;
|
||||
const { api, uploadParams = {}, name, filename, resultField } = props;
|
||||
if (!api || !isFunction(api)) {
|
||||
return warn('upload api must exist and be a function');
|
||||
}
|
||||
try {
|
||||
const res = await props.api?.({
|
||||
const res = await api?.({
|
||||
data: {
|
||||
...(props.uploadParams || {}),
|
||||
...uploadParams,
|
||||
},
|
||||
file: info.file,
|
||||
name: props.name,
|
||||
filename: props.filename,
|
||||
name: name,
|
||||
filename: filename,
|
||||
});
|
||||
if (props.resultField) {
|
||||
info.onSuccess!(res);
|
||||
let result = get(res, resultField);
|
||||
info.onSuccess!(result);
|
||||
} else {
|
||||
// 不传入 resultField 的情况
|
||||
info.onSuccess!(res.data);
|
||||
@@ -190,12 +198,12 @@
|
||||
const list = (fileList.value || [])
|
||||
.filter((item) => item?.status === UploadResultStatus.DONE)
|
||||
.map((item: any) => {
|
||||
if (props.resultField) {
|
||||
return get(item?.response, props.resultField);
|
||||
if (item?.response && props?.resultField) {
|
||||
return item?.response;
|
||||
}
|
||||
return item?.url || item?.response?.url;
|
||||
});
|
||||
return props.multiple ? list : list.length > 0 ? list[0] : '';
|
||||
return list;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -57,7 +57,7 @@
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
// types
|
||||
import { FileItem, UploadResultStatus } from '../types/typing';
|
||||
import { basicProps } from '../props';
|
||||
import { handleFnKey, basicProps } from '../props';
|
||||
import { createTableColumns, createActionColumn } from './data';
|
||||
// utils
|
||||
import { checkImgType, getBase64WithFile } from '../helper';
|
||||
@@ -71,7 +71,7 @@
|
||||
const props = defineProps({
|
||||
...basicProps,
|
||||
previewFileList: {
|
||||
type: Array as PropType<string[]>,
|
||||
type: Array as PropType<string[] | any[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
@@ -161,13 +161,13 @@
|
||||
}
|
||||
|
||||
// 删除
|
||||
function handleRemove(record: FileItem) {
|
||||
const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid);
|
||||
index !== -1 && fileListRef.value.splice(index, 1);
|
||||
isUploadingRef.value = fileListRef.value.some(
|
||||
(item) => item.status === UploadResultStatus.UPLOADING,
|
||||
);
|
||||
emit('delete', record);
|
||||
function handleRemove(obj: Record<handleFnKey, any>) {
|
||||
let { record = {}, uidKey = 'uid' } = obj;
|
||||
const index = fileListRef.value.findIndex((item) => item[uidKey] === record[uidKey]);
|
||||
if (index !== -1) {
|
||||
const removed = fileListRef.value.splice(index, 1);
|
||||
emit('delete', removed[0][uidKey]);
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadApiByItem(item: FileItem) {
|
||||
|
@@ -14,13 +14,17 @@
|
||||
import { watch, ref } from 'vue';
|
||||
import FileList from './FileList.vue';
|
||||
import { BasicModal, useModalInner } from '@/components/Modal';
|
||||
import { previewProps } from '../props';
|
||||
import { FileBasicColumn, PreviewFileItem } from '../types/typing';
|
||||
import { handleFnKey, previewProps } from '../props';
|
||||
import { BaseFileItem, FileBasicColumn, PreviewFileItem } from '../types/typing';
|
||||
import { downloadByUrl } from '@/utils/file/download';
|
||||
import { createPreviewColumns, createPreviewActionColumn } from './data';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { isArray } from '@/utils/is';
|
||||
import { isArray, isFunction } from '@/utils/is';
|
||||
import { BasicColumn } from '@/components/Table';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { buildUUID } from '@/utils/uuid';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const props = defineProps(previewProps);
|
||||
|
||||
@@ -32,13 +36,15 @@
|
||||
const [register] = useModalInner();
|
||||
const { t } = useI18n();
|
||||
|
||||
const fileListRef = ref<PreviewFileItem[] | Array<any>>([]);
|
||||
const fileListRef = ref<BaseFileItem[] | Array<any>>([]);
|
||||
watch(
|
||||
() => props.previewColumns,
|
||||
() => {
|
||||
if (props.previewColumns.length) {
|
||||
if (Array.isArray(props.previewColumns) && props.previewColumns.length) {
|
||||
columns = props.previewColumns;
|
||||
actionColumn = null;
|
||||
} else if (isFunction(props.previewColumns)) {
|
||||
columns = props.previewColumns({ handleRemove, handleAdd });
|
||||
} else {
|
||||
columns = createPreviewColumns();
|
||||
actionColumn = createPreviewActionColumn({ handleRemove, handleDownload });
|
||||
@@ -59,14 +65,15 @@
|
||||
fileListRef.value = value
|
||||
.filter((item) => !!item)
|
||||
.map((item) => {
|
||||
if (typeof item != 'string') {
|
||||
console.error('return value should be string');
|
||||
if (typeof item != 'object') {
|
||||
console.error('return value should be object');
|
||||
return;
|
||||
}
|
||||
return {
|
||||
url: item,
|
||||
type: item.split('.').pop() || '',
|
||||
name: item.split('/').pop() || '',
|
||||
uid: item?.uid,
|
||||
url: item?.url,
|
||||
type: item?.url?.split('.').pop() || '',
|
||||
name: item?.url?.split('/').pop() || '',
|
||||
};
|
||||
});
|
||||
},
|
||||
@@ -74,18 +81,26 @@
|
||||
);
|
||||
|
||||
// 删除
|
||||
function handleRemove(record: PreviewFileItem) {
|
||||
const index = fileListRef.value.findIndex((item) => item.url === record.url);
|
||||
function handleRemove(obj: Record<handleFnKey, any>) {
|
||||
let { record = {}, valueKey = 'url', uidKey = 'uid' } = obj;
|
||||
const index = fileListRef.value.findIndex((item) => item[uidKey] === record[uidKey]);
|
||||
if (index !== -1) {
|
||||
const removed = fileListRef.value.splice(index, 1);
|
||||
emit('delete', removed[0].url);
|
||||
emit(
|
||||
'list-change',
|
||||
fileListRef.value.map((item) => item.url),
|
||||
);
|
||||
emit('delete', removed[0][uidKey]);
|
||||
emit('list-change', fileListRef.value, valueKey);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加
|
||||
function handleAdd(obj: Record<handleFnKey, any>) {
|
||||
let { record = {}, valueKey = 'url', uidKey = 'uid' } = obj;
|
||||
const { maxNumber } = props;
|
||||
if (fileListRef.value.length + fileListRef.value.length > maxNumber) {
|
||||
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
|
||||
}
|
||||
record[uidKey] = record[uidKey] ?? buildUUID();
|
||||
fileListRef.value = [...fileListRef.value, record];
|
||||
emit('list-change', fileListRef.value, valueKey);
|
||||
}
|
||||
// 下载
|
||||
function handleDownload(record: PreviewFileItem) {
|
||||
const { url = '' } = record;
|
||||
|
@@ -5,6 +5,7 @@ import { Progress, Tag } from 'ant-design-vue';
|
||||
import TableAction from '@/components/Table/src/components/TableAction.vue';
|
||||
import ThumbUrl from './ThumbUrl.vue';
|
||||
import { useI18n } from '@/hooks/web/useI18n';
|
||||
import { previewColumnsFnType } from '../props';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -81,7 +82,11 @@ export function createActionColumn(handleRemove: Function): FileBasicColumn {
|
||||
{
|
||||
label: t('component.upload.del'),
|
||||
color: 'error',
|
||||
onClick: handleRemove.bind(null, record),
|
||||
onClick: handleRemove.bind(null, {
|
||||
record,
|
||||
uidKey: 'uid',
|
||||
valueKey: 'url',
|
||||
}),
|
||||
},
|
||||
];
|
||||
return <TableAction actions={actions} outside={true} />;
|
||||
@@ -112,7 +117,7 @@ export function createPreviewActionColumn({
|
||||
handleRemove,
|
||||
handleDownload,
|
||||
}: {
|
||||
handleRemove: Fn;
|
||||
handleRemove: previewColumnsFnType['handleRemove'];
|
||||
handleDownload: Fn;
|
||||
}): BasicColumn {
|
||||
return {
|
||||
@@ -125,7 +130,11 @@ export function createPreviewActionColumn({
|
||||
{
|
||||
label: t('component.upload.del'),
|
||||
color: 'error',
|
||||
onClick: handleRemove.bind(null, record),
|
||||
onClick: handleRemove.bind(null, {
|
||||
record,
|
||||
uidKey: 'uid',
|
||||
valueKey: 'url',
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: t('component.upload.download'),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import type { PropType } from 'vue';
|
||||
import { FileBasicColumn } from './types/typing';
|
||||
import { BaseFileItem, FileBasicColumn } from './types/typing';
|
||||
|
||||
import type { Options } from 'sortablejs';
|
||||
|
||||
@@ -14,15 +14,20 @@ type SortableOptions = Merge<
|
||||
// ...可扩展
|
||||
}
|
||||
>;
|
||||
|
||||
export type handleFnKey = 'record' | 'valueKey' | 'uidKey';
|
||||
export type previewColumnsFnType = {
|
||||
handleRemove: (record: Record<handleFnKey, any>) => any;
|
||||
handleAdd: (record: Record<handleFnKey, any>) => any;
|
||||
};
|
||||
export const previewType = {
|
||||
previewColumns: {
|
||||
type: Array as PropType<BasicColumn[] | FileBasicColumn[]>,
|
||||
default: [],
|
||||
type: [Array, Function] as PropType<
|
||||
BasicColumn[] | ((arg: previewColumnsFnType) => BasicColumn[])
|
||||
>,
|
||||
required: false,
|
||||
},
|
||||
beforePreviewData: {
|
||||
type: Function as PropType<(arg: string[]) => Recordable<any>>,
|
||||
type: Function as PropType<(arg: BaseFileItem[] | any) => Recordable<any>>,
|
||||
default: null,
|
||||
required: false,
|
||||
},
|
||||
@@ -31,6 +36,7 @@ export const previewType = {
|
||||
type ListType = 'text' | 'picture' | 'picture-card';
|
||||
|
||||
export const basicProps = {
|
||||
disabled: { type: Boolean, default: false },
|
||||
listType: {
|
||||
type: String as PropType<ListType>,
|
||||
default: 'picture-card',
|
||||
@@ -107,9 +113,13 @@ export const uploadContainerProps = {
|
||||
|
||||
export const previewProps = {
|
||||
value: {
|
||||
type: Array as PropType<string[]>,
|
||||
type: Array as PropType<BaseFileItem[] | any[]>,
|
||||
default: () => [],
|
||||
},
|
||||
maxNumber: {
|
||||
type: Number as PropType<number>,
|
||||
default: 1,
|
||||
},
|
||||
...previewType,
|
||||
};
|
||||
|
||||
|
@@ -20,6 +20,11 @@ export interface FileItem {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface BaseFileItem {
|
||||
uid: string | number;
|
||||
url: string;
|
||||
name?: string;
|
||||
}
|
||||
export interface PreviewFileItem {
|
||||
url: string;
|
||||
name: string;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { withInstall } from '@/utils';
|
||||
import vxeBasicTable from './src/VxeBasicTable';
|
||||
import { VXETable } from 'vxe-table';
|
||||
import { VxeUI } from 'vxe-table';
|
||||
import VXETablePluginAntd from './src/components';
|
||||
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx';
|
||||
import ExcelJS from 'exceljs';
|
||||
@@ -10,4 +10,4 @@ export const VxeBasicTable = withInstall(vxeBasicTable);
|
||||
export * from 'vxe-table';
|
||||
export * from './src/types';
|
||||
|
||||
VXETable.use(VXETablePluginAntd).use(VXETablePluginExportXLSX, { ExcelJS });
|
||||
VxeUI.use(VXETablePluginAntd).use(VXETablePluginExportXLSX, { ExcelJS });
|
||||
|
@@ -1,22 +1,25 @@
|
||||
import { defineComponent, computed, ref } from 'vue';
|
||||
import { defineComponent, computed, ref, watch } from 'vue';
|
||||
import { BasicTableProps } from './types';
|
||||
import { basicProps } from './props';
|
||||
import { ignorePropKeys } from './const';
|
||||
import { basicEmits } from './emits';
|
||||
import XEUtils from 'xe-utils';
|
||||
import type {
|
||||
import {
|
||||
VxeGridInstance,
|
||||
VxeGridEventProps,
|
||||
GridMethods,
|
||||
TableMethods,
|
||||
TableEditMethods,
|
||||
TableValidatorMethods,
|
||||
VxeUI,
|
||||
VxeGlobalThemeName,
|
||||
VxeGrid,
|
||||
} from 'vxe-table';
|
||||
import { Grid as VxeGrid } from 'vxe-table';
|
||||
|
||||
import { extendSlots } from '@/utils/helper/tsxHelper';
|
||||
import { gridComponentMethodKeys } from './methods';
|
||||
import { omit } from 'lodash-es';
|
||||
import { useRootSetting } from '@/hooks/setting/useRootSetting';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VxeBasicTable',
|
||||
@@ -25,7 +28,14 @@ export default defineComponent({
|
||||
setup(props, { emit, attrs }) {
|
||||
const tableElRef = ref<VxeGridInstance>();
|
||||
const emitEvents: VxeGridEventProps = {};
|
||||
|
||||
const { getDarkMode } = useRootSetting();
|
||||
watch(
|
||||
() => getDarkMode.value,
|
||||
() => {
|
||||
VxeUI.setTheme(getDarkMode.value as VxeGlobalThemeName);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
const extendTableMethods = (methodKeys) => {
|
||||
const funcs: any = {};
|
||||
methodKeys.forEach((name) => {
|
||||
|
@@ -1,20 +1,21 @@
|
||||
import XEUtils from 'xe-utils';
|
||||
import { createDefaultRender, createEditRender, createFormItemRender } from './common';
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
|
||||
export default {
|
||||
renderDefault: createDefaultRender({}, (_, params) => {
|
||||
renderTableDefault: createDefaultRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
renderEdit: createEditRender({}, (_, params) => {
|
||||
renderTableEdit: createEditRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
renderItemContent: createFormItemRender({}, (_, params) => {
|
||||
renderFormItemContent: createFormItemRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,20 +1,21 @@
|
||||
import XEUtils from 'xe-utils';
|
||||
import { createDefaultRender, createEditRender, createFormItemRender } from './common';
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
|
||||
export default {
|
||||
renderDefault: createDefaultRender({}, (_, params) => {
|
||||
renderTableDefault: createDefaultRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
renderEdit: createEditRender({}, (_, params) => {
|
||||
renderTableEdit: createEditRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
renderItemContent: createFormItemRender({}, (_, params) => {
|
||||
renderFormItemContent: createFormItemRender({}, (_, params) => {
|
||||
return {
|
||||
params: XEUtils.get(params, 'row'),
|
||||
};
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import {
|
||||
createEditRender,
|
||||
createDefaultRender,
|
||||
@@ -7,10 +8,10 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
autofocus: 'input.ant-input',
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
tableAutoFocus: 'input.ant-input',
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import { h } from 'vue';
|
||||
import {
|
||||
FormItemContentRenderParams,
|
||||
FormItemRenderOptions,
|
||||
VxeFormItemPropTypes,
|
||||
VxeGlobalRendererHandles,
|
||||
VxeGlobalRendererOptions,
|
||||
} from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import { cellText, createEvents, createProps, getComponent } from './common';
|
||||
@@ -11,8 +12,8 @@ const COMPONENT_NAME = 'AButton';
|
||||
|
||||
export function createEditRender() {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) {
|
||||
const { attrs } = renderOpts;
|
||||
const Component = getComponent(COMPONENT_NAME);
|
||||
@@ -29,8 +30,8 @@ export function createEditRender() {
|
||||
|
||||
export function createDefaultRender() {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) {
|
||||
const { attrs } = renderOpts;
|
||||
const Component = getComponent(COMPONENT_NAME);
|
||||
@@ -50,7 +51,10 @@ export function createDefaultRender() {
|
||||
}
|
||||
|
||||
export function createFormItemRender() {
|
||||
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
|
||||
return function (
|
||||
renderOpts: VxeFormItemPropTypes.ItemRender,
|
||||
params: FormItemContentRenderParams,
|
||||
) {
|
||||
const { attrs, content } = renderOpts;
|
||||
const { property, $form, data } = params;
|
||||
const props = createProps(renderOpts, null);
|
||||
@@ -113,8 +117,8 @@ function createToolbarButtonRender() {
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderDefault: createDefaultRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
renderToolbarButton: createToolbarButtonRender(),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,20 +1,21 @@
|
||||
import {
|
||||
FormItemContentRenderParams,
|
||||
FormItemRenderOptions,
|
||||
VxeFormItemPropTypes,
|
||||
VxeGlobalRendererHandles,
|
||||
VxeGlobalRendererOptions,
|
||||
} from 'vxe-table';
|
||||
import { createDefaultRender, createEditRender, createFormItemRender } from './AButton';
|
||||
|
||||
function createEditButtonRender() {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) {
|
||||
const buttonEditRender = createEditRender();
|
||||
const { children } = renderOpts;
|
||||
if (children) {
|
||||
return children.map(
|
||||
(childRenderOpts: VxeGlobalRendererHandles.RenderEditOptions) =>
|
||||
(childRenderOpts: VxeGlobalRendererHandles.RenderTableEditOptions) =>
|
||||
buttonEditRender(childRenderOpts, params)[0],
|
||||
);
|
||||
}
|
||||
@@ -25,7 +26,7 @@ function createEditButtonRender() {
|
||||
function createDefaultButtonRender() {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
|
||||
params: VxeGlobalRendererHandles.RenderDefaultParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableDefaultParams,
|
||||
) {
|
||||
const buttonDefaultRender = createDefaultRender();
|
||||
const { children } = renderOpts;
|
||||
@@ -40,12 +41,16 @@ function createDefaultButtonRender() {
|
||||
}
|
||||
|
||||
function createButtonItemRender() {
|
||||
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
|
||||
return function (
|
||||
renderOpts: VxeFormItemPropTypes.ItemRender,
|
||||
params: FormItemContentRenderParams,
|
||||
) {
|
||||
const buttonItemRender = createFormItemRender();
|
||||
const { children } = renderOpts;
|
||||
if (children) {
|
||||
return children.map(
|
||||
(childRenderOpts: FormItemRenderOptions) => buttonItemRender(childRenderOpts, params)[0],
|
||||
(childRenderOpts: VxeFormItemPropTypes.ItemRender) =>
|
||||
buttonItemRender(childRenderOpts, params)[0],
|
||||
);
|
||||
}
|
||||
return [];
|
||||
@@ -53,7 +58,7 @@ function createButtonItemRender() {
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditButtonRender(),
|
||||
renderDefault: createDefaultButtonRender(),
|
||||
renderItemContent: createButtonItemRender(),
|
||||
};
|
||||
renderTableEdit: createEditButtonRender(),
|
||||
renderTableDefault: createDefaultButtonRender(),
|
||||
renderFormItemContent: createButtonItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import {
|
||||
createEditRender,
|
||||
@@ -21,7 +21,7 @@ function matchCascaderData(index: number, list: any[], values: any[], labels: an
|
||||
|
||||
function getCascaderCellValue(
|
||||
renderOpts: VxeGlobalRendererHandles.RenderOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableCellParams,
|
||||
) {
|
||||
const { props = {} } = renderOpts;
|
||||
const { row, column } = params;
|
||||
@@ -35,8 +35,8 @@ function getCascaderCellValue(
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getCascaderCellValue),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getCascaderCellValue),
|
||||
};
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getCascaderCellValue),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getCascaderCellValue),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { createFormItemRender } from './common';
|
||||
|
||||
export default {
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import {
|
||||
createCellRender,
|
||||
@@ -9,7 +9,9 @@ import {
|
||||
|
||||
export function getDatePickerCellValue(
|
||||
renderOpts: VxeGlobalRendererHandles.RenderOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
|
||||
params:
|
||||
| VxeGlobalRendererHandles.RenderTableCellParams
|
||||
| VxeGlobalRendererHandles.ExportMethodParams,
|
||||
defaultFormat: string,
|
||||
) {
|
||||
const { props = {} } = renderOpts;
|
||||
@@ -22,12 +24,12 @@ export function getDatePickerCellValue(
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getDatePickerCellValue, () => {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getDatePickerCellValue, () => {
|
||||
return ['YYYY-MM-DD'];
|
||||
}),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
return ['YYYY-MM-DD'];
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { h } from 'vue';
|
||||
import { VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { getComponent } from './common';
|
||||
|
||||
function createEmptyRender() {
|
||||
return function (renderOpts: VxeGlobalRendererHandles.RenderEmptyOptions) {
|
||||
return function (renderOpts: VxeGlobalRendererHandles.RenderTableEmptyOptions) {
|
||||
const { name, attrs, props } = renderOpts;
|
||||
|
||||
const Component = getComponent(name);
|
||||
@@ -23,5 +23,5 @@ function createEmptyRender() {
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEmpty: createEmptyRender(),
|
||||
};
|
||||
renderTableEmptyView: createEmptyRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import {
|
||||
createEditRender,
|
||||
createDefaultRender,
|
||||
@@ -7,10 +8,10 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
autofocus: 'input.ant-input',
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
tableAutoFocus: 'input.ant-input',
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import {
|
||||
createEditRender,
|
||||
createFilterRender,
|
||||
@@ -7,10 +8,10 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
autofocus: 'input.ant-input-number-input',
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
tableAutoFocus: 'input.ant-input-number-input',
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import {
|
||||
createEditRender,
|
||||
createDefaultRender,
|
||||
@@ -8,10 +9,10 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
renderToolbarTool: createToolbarToolRender(),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { getDatePickerCellValue } from './ADatePicker';
|
||||
import {
|
||||
createCellRender,
|
||||
@@ -7,12 +8,12 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getDatePickerCellValue, () => {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getDatePickerCellValue, () => {
|
||||
return ['YYYY-MM'];
|
||||
}),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
return ['YYYY-MM'];
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { createFormItemRender } from './common';
|
||||
|
||||
export default {
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeColumnPropTypes, VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import {
|
||||
createCellRender,
|
||||
@@ -9,7 +9,9 @@ import {
|
||||
|
||||
function getRangePickerCellValue(
|
||||
renderOpts: VxeColumnPropTypes.EditRender,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
|
||||
params:
|
||||
| VxeGlobalRendererHandles.RenderTableCellParams
|
||||
| VxeGlobalRendererHandles.ExportMethodParams,
|
||||
) {
|
||||
const { props = {} } = renderOpts;
|
||||
const { row, column } = params;
|
||||
@@ -23,8 +25,8 @@ function getRangePickerCellValue(
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getRangePickerCellValue),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getRangePickerCellValue),
|
||||
};
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getRangePickerCellValue),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getRangePickerCellValue),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import {
|
||||
createEditRender,
|
||||
createDefaultRender,
|
||||
@@ -7,9 +8,9 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { ComponentOptions, h, resolveComponent } from 'vue';
|
||||
import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeColumnPropTypes, VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import {
|
||||
cellText,
|
||||
@@ -32,7 +32,7 @@ function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.Ren
|
||||
function createEditRender() {
|
||||
return function (
|
||||
renderOpts: VxeColumnPropTypes.EditRender,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) {
|
||||
const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
|
||||
const { row, column, $table } = params;
|
||||
@@ -100,8 +100,8 @@ function createEditRender() {
|
||||
}
|
||||
|
||||
function getSelectCellValue(
|
||||
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableCellParams,
|
||||
) {
|
||||
const {
|
||||
options = [],
|
||||
@@ -144,7 +144,7 @@ function getSelectCellValue(
|
||||
function createFilterRender() {
|
||||
return function (
|
||||
renderOpts: VxeColumnPropTypes.FilterRender,
|
||||
params: VxeGlobalRendererHandles.RenderFilterParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableFilterParams,
|
||||
) {
|
||||
const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
|
||||
const groupOptions = optionGroupProps.options || 'options';
|
||||
@@ -249,10 +249,10 @@ function createFilterRender() {
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getSelectCellValue),
|
||||
renderFilter: createFilterRender(),
|
||||
defaultFilterMethod(params) {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getSelectCellValue),
|
||||
renderTableFilter: createFilterRender(),
|
||||
tableFilterDefaultMethod(params) {
|
||||
const { option, row, column } = params;
|
||||
const { data } = option;
|
||||
const { field, filterRender: renderOpts } = column;
|
||||
@@ -266,6 +266,6 @@ export default {
|
||||
}
|
||||
return cellValue == data;
|
||||
},
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getSelectCellValue),
|
||||
};
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getSelectCellValue),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -9,11 +9,12 @@ import {
|
||||
createFormItemRender,
|
||||
getComponent,
|
||||
} from './common';
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
|
||||
export default {
|
||||
renderDefault: createDefaultRender(),
|
||||
renderEdit: createEditRender(),
|
||||
renderFilter(renderOpts, params) {
|
||||
renderTableDefault: createDefaultRender(),
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableFilter(renderOpts, params) {
|
||||
const { column } = params;
|
||||
const { name, attrs } = renderOpts;
|
||||
const Component = getComponent(name);
|
||||
@@ -48,6 +49,6 @@ export default {
|
||||
),
|
||||
];
|
||||
},
|
||||
defaultFilterMethod: createDefaultFilterRender(),
|
||||
renderItemContent: createFormItemRender(),
|
||||
};
|
||||
tableFilterDefaultMethod: createDefaultFilterRender(),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { getDatePickerCellValue } from './ADatePicker';
|
||||
import {
|
||||
createEditRender,
|
||||
@@ -7,12 +8,12 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getDatePickerCellValue, () => {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getDatePickerCellValue, () => {
|
||||
return ['HH:mm:ss'];
|
||||
}),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
return ['HH:mm:ss'];
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VxeGlobalRendererHandles } from 'vxe-table';
|
||||
import { VxeGlobalRendererHandles, VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
import {
|
||||
createEditRender,
|
||||
@@ -10,7 +10,9 @@ import {
|
||||
|
||||
function getTreeSelectCellValue(
|
||||
renderOpts: VxeGlobalRendererHandles.RenderOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
|
||||
params:
|
||||
| VxeGlobalRendererHandles.RenderTableCellParams
|
||||
| VxeGlobalRendererHandles.ExportMethodParams,
|
||||
) {
|
||||
const { props = {} } = renderOpts;
|
||||
const { treeData, treeCheckable } = props;
|
||||
@@ -28,8 +30,8 @@ function getTreeSelectCellValue(
|
||||
}
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getTreeSelectCellValue),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getTreeSelectCellValue),
|
||||
};
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getTreeSelectCellValue),
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getTreeSelectCellValue),
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { getDatePickerCellValue } from './ADatePicker';
|
||||
import {
|
||||
createEditRender,
|
||||
@@ -7,12 +8,12 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getDatePickerCellValue, () => {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getDatePickerCellValue, () => {
|
||||
return ['YYYY-WW周'];
|
||||
}),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
return ['YYYY-WW周'];
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { VxeGlobalRendererOptions } from 'vxe-table';
|
||||
import { getDatePickerCellValue } from './ADatePicker';
|
||||
import {
|
||||
createEditRender,
|
||||
@@ -7,12 +8,12 @@ import {
|
||||
} from './common';
|
||||
|
||||
export default {
|
||||
renderEdit: createEditRender(),
|
||||
renderCell: createCellRender(getDatePickerCellValue, () => {
|
||||
renderTableEdit: createEditRender(),
|
||||
renderTableCell: createCellRender(getDatePickerCellValue, () => {
|
||||
return ['YYYY'];
|
||||
}),
|
||||
renderItemContent: createFormItemRender(),
|
||||
exportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
renderFormItemContent: createFormItemRender(),
|
||||
tableExportMethod: createExportMethod(getDatePickerCellValue, () => {
|
||||
return ['YYYY'];
|
||||
}),
|
||||
};
|
||||
} as VxeGlobalRendererOptions;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ComponentOptions, h } from 'vue';
|
||||
import {
|
||||
FormItemContentRenderParams,
|
||||
FormItemRenderOptions,
|
||||
VxeFormItemPropTypes,
|
||||
VxeGlobalRendererHandles,
|
||||
} from 'vxe-table';
|
||||
import XEUtils from 'xe-utils';
|
||||
@@ -160,12 +160,12 @@ export function createDefaultRender(
|
||||
defaultProps?: { [key: string]: any },
|
||||
callBack?: (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
|
||||
params: VxeGlobalRendererHandles.RenderDefaultParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableDefaultParams,
|
||||
) => Record<string, any>,
|
||||
) {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions,
|
||||
params: VxeGlobalRendererHandles.RenderDefaultParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableDefaultParams,
|
||||
) {
|
||||
const { row, column, $table } = params;
|
||||
const { name, attrs } = renderOpts;
|
||||
@@ -195,13 +195,13 @@ export function createDefaultRender(
|
||||
export function createEditRender(
|
||||
defaultProps?: { [key: string]: any },
|
||||
callBack?: (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) => Record<string, any>,
|
||||
) {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderEditParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableEditOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableEditParams,
|
||||
) {
|
||||
const { row, column, $table } = params;
|
||||
const { name, attrs } = renderOpts;
|
||||
@@ -232,12 +232,12 @@ export function createFilterRender(
|
||||
defaultProps?: { [key: string]: any },
|
||||
callBack?: (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
|
||||
params: VxeGlobalRendererHandles.RenderFilterParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableFilterParams,
|
||||
) => Record<string, any>,
|
||||
) {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderFilterOptions,
|
||||
params: VxeGlobalRendererHandles.RenderFilterParams,
|
||||
params: VxeGlobalRendererHandles.RenderTableFilterParams,
|
||||
) {
|
||||
const { column } = params;
|
||||
const { name, attrs } = renderOpts;
|
||||
@@ -287,7 +287,7 @@ export function createFilterRender(
|
||||
*/
|
||||
|
||||
export function createDefaultFilterRender() {
|
||||
return function (params: VxeGlobalRendererHandles.FilterMethodParams) {
|
||||
return function (params: VxeGlobalRendererHandles.TableFilterMethodParams) {
|
||||
const { option, row, column } = params;
|
||||
const { data } = option;
|
||||
const cellValue = XEUtils.get(row, column.field as string);
|
||||
@@ -301,11 +301,14 @@ export function createDefaultFilterRender() {
|
||||
export function createFormItemRender(
|
||||
defaultProps?: { [key: string]: any },
|
||||
callBack?: (
|
||||
renderOpts: FormItemRenderOptions,
|
||||
renderOpts: VxeFormItemPropTypes.ItemRender,
|
||||
params: FormItemContentRenderParams,
|
||||
) => Record<string, any>,
|
||||
) {
|
||||
return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
|
||||
return function (
|
||||
renderOpts: VxeFormItemPropTypes.ItemRender,
|
||||
params: FormItemContentRenderParams,
|
||||
) {
|
||||
const args = (callBack && callBack(renderOpts, params)) ?? {};
|
||||
const { data, property, $form } = params;
|
||||
const { name } = renderOpts;
|
||||
@@ -344,13 +347,13 @@ export function createFormItemRender(
|
||||
export function createCellRender(
|
||||
getSelectCellValue: Function,
|
||||
callBack?: (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableCellParams,
|
||||
) => Array<any>,
|
||||
) {
|
||||
return function (
|
||||
renderOpts: VxeGlobalRendererHandles.RenderCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderCellParams,
|
||||
renderOpts: VxeGlobalRendererHandles.RenderTableCellOptions,
|
||||
params: VxeGlobalRendererHandles.RenderTableCellParams,
|
||||
) {
|
||||
const args = (callBack && callBack(renderOpts, params)) ?? [];
|
||||
const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { VXETableCore, VxeGlobalInterceptorHandles } from 'vxe-table';
|
||||
import { VxeUIExport, VxeGlobalInterceptorHandles } from 'vxe-table';
|
||||
import AAutoComplete from './AAutoComplete';
|
||||
import AInput from './AInput';
|
||||
import AInputNumber from './AInputNumber';
|
||||
@@ -50,7 +50,7 @@ function getEventTargetNode(evnt: any, container: HTMLElement, className: string
|
||||
function handleClearEvent(
|
||||
params:
|
||||
| VxeGlobalInterceptorHandles.InterceptorClearFilterParams
|
||||
| VxeGlobalInterceptorHandles.InterceptorClearActivedParams
|
||||
| VxeGlobalInterceptorHandles.InterceptorClearEditParams
|
||||
| VxeGlobalInterceptorHandles.InterceptorClearAreasParams,
|
||||
) {
|
||||
const { $event } = params;
|
||||
@@ -73,10 +73,10 @@ function handleClearEvent(
|
||||
* 基于 vxe-table 表格的适配插件,用于兼容 ant-design-vue 组件库
|
||||
*/
|
||||
export const VXETablePluginAntd = {
|
||||
install(vxetablecore: VXETableCore) {
|
||||
install(vxetablecore: VxeUIExport) {
|
||||
const { interceptor, renderer } = vxetablecore;
|
||||
|
||||
renderer.mixin({
|
||||
const customRenderComponents = {
|
||||
AAutoComplete,
|
||||
AInput,
|
||||
AInputNumber,
|
||||
@@ -99,16 +99,21 @@ export const VXETablePluginAntd = {
|
||||
AEmpty,
|
||||
AInputSearch,
|
||||
AYearPicker,
|
||||
};
|
||||
|
||||
Object.keys(customRenderComponents).forEach((name) => {
|
||||
if (renderer.get(name)) return;
|
||||
renderer.add(name, customRenderComponents[name]);
|
||||
});
|
||||
|
||||
interceptor.add('event.clearFilter', handleClearEvent);
|
||||
interceptor.add('event.clearActived', handleClearEvent);
|
||||
interceptor.add('event.clearEdit', handleClearEvent);
|
||||
interceptor.add('event.clearAreas', handleClearEvent);
|
||||
},
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) {
|
||||
window.VXETable.use(VXETablePluginAntd);
|
||||
if (typeof window !== 'undefined' && window.VxeUI && window.VxeUI.use) {
|
||||
window.VxeUI.use(VXETablePluginAntd);
|
||||
}
|
||||
|
||||
export default VXETablePluginAntd;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user