diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 000000000..e7c12fd0f --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,5 @@ +Android 4.1 +IOS 7.1 +Chrome > 31 +ff > 31 +ie >= 11 \ No newline at end of file diff --git a/.env.base b/.env.base new file mode 100644 index 000000000..5e6ecf5e4 --- /dev/null +++ b/.env.base @@ -0,0 +1,32 @@ +# 环境 +VITE_NODE_ENV=development + +# 接口前缀 +VITE_API_BASE_PATH=http://39.104.23.25:48080/admin-api/ + +# 打包路径 +VITE_BASE_PATH=/ + +# 标题 +VITE_APP_TITLE=ElementAdmin + +# 是否全量引入element-plus样式 +VITE_USE_ALL_ELEMENT_PLUS_STYLE=true + +# 是否开启mock +VITE_USE_MOCK=true + +# 是否使用在线图标 +VITE_USE_ONLINE_ICON=true + +# 是否隐藏全局设置按钮 +VITE_HIDE_GLOBAL_SETTING=false + +# 是否启用租户功能 +VITE_APP_TENANT_ENABLE=true + +# 默认租户名称 +VITE_APP_DEFAULT_LOGIN_TENANT=芋道源码 + +#开启验证码 +VITE_APP_CAPTCHA_ENABLE=true diff --git a/.env.dev b/.env.dev new file mode 100644 index 000000000..a39a35ba8 --- /dev/null +++ b/.env.dev @@ -0,0 +1,45 @@ +# 环境 +VITE_NODE_ENV=production + +# 接口前缀 +VITE_API_BASE_PATH=http://39.104.23.25:48080/admin-api/ + + +# 打包路径 +VITE_BASE_PATH=/dist-dev/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=true + +# 输出路径 +VITE_OUT_DIR=dist-dev + +# 标题 +VITE_APP_TITLE=ElementAdmin + +# 是否包分析 +VITE_USE_BUNDLE_ANALYZER=false + +# 是否全量引入element-plus样式 +VITE_USE_ALL_ELEMENT_PLUS_STYLE=false + +# 是否开启mock +VITE_USE_MOCK=true + +# 是否切割css +VITE_USE_CSS_SPLIT=true + +# 是否使用在线图标 +VITE_USE_ONLINE_ICON=true + +# 是否隐藏全局设置按钮 +VITE_HIDE_GLOBAL_SETTING=false + +#开启验证码 +VITE_APP_CAPTCHA_ENABLE=true diff --git a/.env.gitee b/.env.gitee new file mode 100644 index 000000000..278bab522 --- /dev/null +++ b/.env.gitee @@ -0,0 +1,44 @@ +# 环境 +VITE_NODE_ENV=production + +# 接口前缀 +VITE_API_BASE_PATH=http://39.104.23.25:48080/admin-api/ + +# 打包路径 +VITE_BASE_PATH=/vue-element-plus-admin/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 输出路径 +VITE_OUT_DIR=dist-pro + +# 标题 +VITE_APP_TITLE=ElementAdmin + +# 是否包分析 +VITE_USE_BUNDLE_ANALYZER=false + +# 是否全量引入element-plus样式 +VITE_USE_ALL_ELEMENT_PLUS_STYLE=false + +# 是否开启mock +VITE_USE_MOCK=true + +# 是否切割css +VITE_USE_CSS_SPLIT=true + +# 是否使用在线图标 +VITE_USE_ONLINE_ICON=true + +# 是否隐藏全局设置按钮 +VITE_HIDE_GLOBAL_SETTING=false + +#开启验证码 +VITE_APP_CAPTCHA_ENABLE=true diff --git a/.env.pro b/.env.pro new file mode 100644 index 000000000..1baaa8da7 --- /dev/null +++ b/.env.pro @@ -0,0 +1,44 @@ +# 环境 +VITE_NODE_ENV=production + +# 接口前缀 +VITE_API_BASE_PATH=http://39.104.23.25:48080/admin-api/ + +# 打包路径 +VITE_BASE_PATH=/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 输出路径 +VITE_OUT_DIR=dist-pro + +# 标题 +VITE_APP_TITLE=ElementAdmin + +# 是否包分析 +VITE_USE_BUNDLE_ANALYZER=true + +# 是否全量引入element-plus样式 +VITE_USE_ALL_ELEMENT_PLUS_STYLE=false + +# 是否开启mock +VITE_USE_MOCK=true + +# 是否切割css +VITE_USE_CSS_SPLIT=true + +# 是否使用在线图标 +VITE_USE_ONLINE_ICON=false + +# 是否隐藏全局设置按钮 +VITE_HIDE_GLOBAL_SETTING=false + +#开启验证码 +VITE_APP_CAPTCHA_ENABLE=true diff --git a/.env.test b/.env.test new file mode 100644 index 000000000..afd4ad91b --- /dev/null +++ b/.env.test @@ -0,0 +1,44 @@ +# 环境 +VITE_NODE_ENV=production + +# 接口前缀 +VITE_API_BASE_PATH=http://39.104.23.25:48080/admin-api/ + +# 打包路径 +VITE_BASE_PATH=/dist-test/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=true + +# 输出路径 +VITE_OUT_DIR=dist-test + +# 标题 +VITE_APP_TITLE=ElementAdmin + +# 是否包分析 +VITE_USE_BUNDLE_ANALYZER=false + +# 是否全量引入element-plus样式 +VITE_USE_ALL_ELEMENT_PLUS_STYLE=false + +# 是否开启mock +VITE_USE_MOCK=true + +# 是否切割css +VITE_USE_CSS_SPLIT=false + +# 是否使用在线图标 +VITE_USE_ONLINE_ICON=true + +# 是否隐藏全局设置按钮 +VITE_HIDE_GLOBAL_SETTING=false + +#开启验证码 +VITE_APP_CAPTCHA_ENABLE=true diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml new file mode 100644 index 000000000..f9cd3d77b --- /dev/null +++ b/.github/workflows/auto-merge.yml @@ -0,0 +1,131 @@ +name: Automerge + +on: + pull_request: + types: + - labeled + - unlabeled + - synchronize + - opened + - edited + - ready_for_review + - reopened + - unlocked + pull_request_review: + types: + - submitted + status: {} + +jobs: + # 合并发布版本的 pr 到 master + auto-merge: + runs-on: ubuntu-latest + steps: + - name: Automerge + uses: 'pascalgn/automerge-action@v0.14.3' + env: + BASE_BRANCHES: 'release' + GITHUB_TOKEN: '${{ secrets.TOKEN }}' + MERGE_LABELS: '' + MERGE_FILTER_AUTHOR: 'kailong321200875' + + push-to-gh-pages: + needs: [auto-merge] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: use Node.js 18 + uses: actions/setup-node@v2.1.2 + with: + node-version: '18.x' + + - name: Set SSH Environment + env: + DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + run: | + mkdir -p ~/.ssh/ + echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan github.com > ~/.ssh/known_hosts + chmod 700 ~/.ssh && chmod 600 ~/.ssh/* + git config --local user.email "321200875@qq.com" + git config --local user.name "kailong321200875" + + # 发布到 github + - name: Build Github + run: | + pnpm install --no-frozen-lockfile + pnpm run build:pro + + - name: Deploy Github + uses: peaceiris/actions-gh-pages@v3 + with: + deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}} + publish_branch: gh-pages + publish_dir: ./dist-pro + force_orphan: true + cname: element-plus-admin.cn + + push-to-gh-pages-gitee: + needs: [auto-merge] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: use Node.js 18 + uses: actions/setup-node@v2.1.2 + with: + node-version: '18.x' + + - name: Set SSH Environment + env: + DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} + run: | + mkdir -p ~/.ssh/ + echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan github.com > ~/.ssh/known_hosts + chmod 700 ~/.ssh && chmod 600 ~/.ssh/* + git config --local user.email "321200875@qq.com" + git config --local user.name "kailong321200875" + + - name: Build Gitee + run: | + pnpm install --no-frozen-lockfile + pnpm run build:gitee + + # 发布到 gitee + - name: Deploy Gitee + uses: peaceiris/actions-gh-pages@v3 + with: + deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}} + publish_branch: gh-pages-gitee + publish_dir: ./dist-pro + force_orphan: true + + - name: Sync Github Repos To Gitee # 名字随便起 + uses: Yikun/hub-mirror-action@v1.1 # 使用Yikun/hub-mirror-action + with: + src: github/kailong321200875 # 源端账户名(github) + dst: gitee/kailong110120130 # 目的端账户名(gitee) + dst_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} # SSH密钥对中的私钥 + dst_token: ${{ secrets.GITEE_TOKEN }} # Gitee账户的私人令牌 + account_type: user # 账户类型 + clone_style: 'https' # 使用https方式进行clone,也可以使用ssh + debug: true # 启用后会显示所有执行命令 + force_update: true # 启用后,强制同步,即强制覆盖目的端仓库 + static_list: 'vue-element-plus-admin' # 静态同步列表,在此填写需要同步的仓库名称,可填写多个 + timeout: '600s' # git超时设置,超时后会自动重试git操作 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..2c1144491 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,19 @@ +on: + push: + branches: + - release + +name: Release + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: GoogleCloudPlatform/release-please-action@v3 + id: release + with: + token: ${{ secrets.TOKEN }} + default-branch: release + release-type: node + package-name: standard-version + changelog-types: '[{"type": "types", "section":"Types", "hidden": false},{"type": "revert", "section":"Reverts", "hidden": false},{"type": "feat", "section": "Features", "hidden": false},{"type": "fix", "section": "Bug Fixes", "hidden": false},{"type": "improvement", "section": "Feature Improvements", "hidden": false},{"type": "docs", "section":"Docs", "hidden": false},{"type": "style", "section":"Styling", "hidden": false},{"type": "refactor", "section":"Code Refactoring", "hidden": false},{"type": "perf", "section":"Performance Improvements", "hidden": false},{"type": "test", "section":"Tests", "hidden": false},{"type": "build", "section":"Build System", "hidden": false},{"type": "ci", "section":"CI", "hidden":false}]' diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..1cfd7d52e --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +/dist* +*-lock.* +pnpm-debug +stats.html +.idea +.vtj/histories \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 000000000..34eed8b28 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npx --no -- commitlint --edit $1 \ No newline at end of file diff --git a/.husky/lintstagedrc.cjs b/.husky/lintstagedrc.cjs new file mode 100644 index 000000000..fd96fcbf4 --- /dev/null +++ b/.husky/lintstagedrc.cjs @@ -0,0 +1,9 @@ +module.exports = { + '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'], + '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --parser json --write'], + 'package.json': ['prettier --write'], + '*.vue': ['prettier --write', 'stylelint --fix'], + '*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write'], + '*.md': ['prettier --write'], + '*.hbs': ['prettier --write'] +} diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..d96ed69c6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npm run ts:check +npm run lint:lint-staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..4ff8c9d0c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +/node_modules/** +/dist/ +/dist* +/public/* +/docs/* +/src/types/env.d.ts +/docs/**/* +/plop/**/* +CHANGELOG diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 000000000..aa605b498 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,6 @@ +/dist/* +/public/* +public/* +/dist* +/src/types/env.d.ts +/docs/**/* diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..62a1b221f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["vue.volar", "lokalise.i18n-ally"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..c6be8a8da --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "prettier.enable": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "i18n-ally.localesPaths": ["src/locales"], + "i18n-ally.keystyle": "nested", + "i18n-ally.sortKeys": true, + "i18n-ally.namespace": false, + "i18n-ally.enabledParsers": ["ts"], + "i18n-ally.sourceLanguage": "en", + "i18n-ally.displayLanguage": "zh-CN", + "i18n-ally.enabledFrameworks": ["vue", "react"], + "god.tsconfig": "./tsconfig.json" +} diff --git a/.vtj/files/7pdk4mxyf.json b/.vtj/files/7pdk4mxyf.json new file mode 100644 index 000000000..f3d5029e5 --- /dev/null +++ b/.vtj/files/7pdk4mxyf.json @@ -0,0 +1,313 @@ +{ + "name": "Users", + "locked": false, + "inject": [], + "state": { + "keyword": { + "type": "JSExpression", + "value": "''" + } + }, + "lifeCycles": {}, + "methods": { + "loader": { + "type": "JSFunction", + "value": "(data) => {\n return this.getData(data)\n}" + }, + "search": { + "type": "JSFunction", + "value": "() => {\n this.$refs.gridRef.search()\n}" + }, + "rowAction": { + "type": "JSFunction", + "value": "(row) => {\n this.$message.info('click row id: ' + row.id)\n}" + } + }, + "computed": { + "columns": { + "type": "JSFunction", + "value": "() => {\n return [\n {\n type: 'checkbox',\n width: 40\n },\n {\n type: 'seq',\n width: 60,\n title: '序号'\n },\n {\n field: 'name',\n title: '名称',\n minWidth: 100\n },\n {\n field: 'label',\n title: '描述',\n minWidth: 100\n },\n {\n field: 'isDefault',\n title: '默认角色',\n minWidth: 100,\n slots: {\n default: 'isDefault'\n }\n },\n {\n field: 'order',\n title: '排序',\n minWidth: 100,\n sortable: true\n },\n {\n field: 'desc',\n title: '备注',\n minWidth: 100\n },\n {\n field: 'createdAt',\n title: '创建时间',\n minWidth: 140\n },\n {\n field: 'actions',\n title: '操作',\n width: 160,\n slots: {\n default: 'actions'\n }\n }\n ]\n}" + } + }, + "watch": [], + "css": "", + "props": [], + "emits": [], + "slots": [], + "dataSources": { + "getData": { + "name": "getData", + "test": { + "type": "JSFunction", + "value": "() => this.runApi({\n /* 在这里可输入接口参数 */\n})" + }, + "type": "mock", + "label": "模拟数据", + "mockTemplate": { + "type": "JSFunction", + "value": "(params) => {\n const { page = 1, pageSize = 50 } = params || {};\n const total = 1000;\n return {\n [`list|${pageSize}`]: [{\n id: '@guid',\n name: '@cname',\n label: '@ctitle',\n 'isDefault|1': '@boolean',\n 'order|+1': 1,\n desc: '@cparagraph',\n createdAt: '@date(yyyy-MM-dd hh:mm:ss)'\n }],\n total,\n page,\n limit: pageSize\n };\n}" + } + } + }, + "__VTJ_BLOCK__": true, + "__VERSION__": "1736401534792", + "id": "7pdk4mxyf", + "nodes": [ + { + "id": "1kqd4haeckr", + "name": "XGrid", + "from": "@vtj/ui", + "invisible": false, + "locked": false, + "children": [ + { + "id": "1mp9b7mk9wj", + "name": "ElInput", + "from": "element-plus", + "invisible": false, + "locked": false, + "slot": { + "name": "toolbar__buttons", + "params": [] + }, + "children": [ + { + "id": "2ax97lz9cox", + "name": "ElButton", + "from": "element-plus", + "invisible": false, + "locked": false, + "slot": { + "name": "append", + "params": [] + }, + "children": "查询", + "props": { + "type": "primary" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "this.search" + }, + "modifiers": {} + } + } + } + ], + "props": { + "style": { + "width": "300px", + "margin-right": "10px" + }, + "placeholder": "请输入查询关键字" + }, + "directives": [ + { + "id": "l36jhkywal", + "name": "vModel", + "arg": "modelValue", + "value": { + "type": "JSExpression", + "value": "this.state.keyword" + } + } + ], + "events": {} + }, + { + "id": "2ammdsu07o6", + "name": "ElButton", + "from": "element-plus", + "invisible": false, + "locked": false, + "slot": { + "name": "toolbar__buttons", + "params": [] + }, + "children": "新增", + "props": { + "icon": "Plus", + "type": "primary" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "() => {\n this.$message.info('click add button')\n}" + }, + "modifiers": {} + } + } + }, + { + "id": "257nvaelda4", + "name": "ElButton", + "from": "element-plus", + "invisible": false, + "locked": false, + "slot": { + "name": "toolbar__buttons", + "params": [] + }, + "children": "批量删除", + "props": { + "icon": "Delete", + "type": "danger" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "() => {\n const rows = this.$refs.gridRef.getSelected();\n if (rows.length) {\n this.$message.info('delete data rows: ' + rows.length);\n } else {\n this.$message.warning('请选择需要删除的数据项');\n }\n}" + }, + "modifiers": {} + } + } + }, + { + "id": "o52fisb3kt", + "name": "ElTag", + "from": "element-plus", + "invisible": false, + "locked": false, + "slot": { + "name": "isDefault", + "params": [] + }, + "children": { + "type": "JSExpression", + "value": "this.context.scope_1kqd4haeckr.row.isDefault ? '是' : '否'" + }, + "props": { + "type": { + "type": "JSExpression", + "value": "this.context.scope_1kqd4haeckr.row.isDefault ? 'success' : 'info'" + } + }, + "directives": [], + "events": {} + }, + { + "id": "1ft4np8i6i1", + "name": "XAction", + "from": "@vtj/ui", + "invisible": false, + "locked": false, + "slot": { + "name": "actions", + "params": [] + }, + "children": [], + "props": { + "mode": "icon", + "size": "default", + "type": "primary", + "label": "编辑" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "() => {\n this.rowAction(this.context.scope_1kqd4haeckr.row)\n}" + }, + "modifiers": {} + } + } + }, + { + "id": "1e8ewprm6ts", + "name": "XAction", + "from": "@vtj/ui", + "invisible": false, + "locked": false, + "slot": { + "name": "actions", + "params": [] + }, + "children": [], + "props": { + "mode": "icon", + "size": "default", + "type": "primary", + "label": "设置" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "() => {\n this.rowAction(this.context.scope_1kqd4haeckr.row)\n}" + }, + "modifiers": {} + } + } + }, + { + "id": "2a1cq8bhwej", + "name": "XAction", + "from": "@vtj/ui", + "invisible": false, + "locked": false, + "slot": { + "name": "actions", + "params": [] + }, + "children": [], + "props": { + "mode": "icon", + "size": "default", + "type": "danger", + "label": "删除" + }, + "directives": [], + "events": { + "click": { + "name": "click", + "handler": { + "type": "JSFunction", + "value": "async () => {\n const ret = await this.$confirm('确定删除?', '提示', { type: 'warning' }).catch(() => false);\n if (ret) {\n this.rowAction(this.context.scope_1kqd4haeckr.row)\n }\n}" + }, + "modifiers": {} + } + } + } + ], + "props": { + "ref": "gridRef", + "pager": true, + "height": "auto", + "loader": { + "type": "JSExpression", + "value": "this.loader" + }, + "columns": { + "type": "JSExpression", + "value": "this.columns.value" + }, + "resizable": true, + "customable": true, + "style": { + "background-color": "#FFFFFF", + "padding-top": "10px", + "padding-left": "10px", + "padding-right": "10px", + "padding-bottom": "10px", + "border-radius": "4px 4px 4px 4px" + } + }, + "directives": [], + "events": {} + } + ] +} diff --git a/.vtj/materials/vue-element-plus-admin.json b/.vtj/materials/vue-element-plus-admin.json new file mode 100644 index 000000000..9632721e6 --- /dev/null +++ b/.vtj/materials/vue-element-plus-admin.json @@ -0,0 +1,15315 @@ +{ + "div": { + "name": "div", + "label": "容器", + "categoryId": "html", + "snippet": { + "children": "容器文本内容示例" + } + }, + "span": { + "name": "span", + "label": "内联", + "categoryId": "html", + "snippet": { + "children": "内联容器文本内容示例" + } + }, + "a": { + "name": "a", + "label": "链接", + "categoryId": "html", + "props": [ + { + "name": "href", + "label": "href", + "setters": "InputSetter" + } + ], + "snippet": { + "children": "链接文本内容示例", + "props": { + "href": "#" + } + } + }, + "img": { + "name": "img", + "label": "图片", + "categoryId": "html", + "childIncludes": false, + "props": [ + { + "name": "src", + "label": "src", + "setters": "InputSetter" + }, + { + "name": "width", + "label": "width", + "setters": "InputSetter" + }, + { + "name": "height", + "label": "height", + "setters": "InputSetter" + } + ], + "snippet": { + "props": { + "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAEACAYAAADCyK/GAAAAAXNSR0IArs4c6QAAIABJREFUeF7tfWmgXFWZ7Vq7bgKCYCvdiGmgAbEVxREEobsDoZFBBYJQdSohARQIIi0CIhigNWmRgKiAAyBDEAO5deo6MDWgoAR4NpOtgiL6WhRlVhsHJknu2eu9UzdIxnur6oy7zj5/s/f61re+fVfqDPvbhL+8Aq4qUNdkGPwbpf1BvB3AwwAeEngdgOsR8ieupuZ556MA8wnjo3gFUlbgvdqUk3ERpL3GQf4NyeusxXV47rHv4Jopz6bMwsM5roA3QMcLWEn6db2UBrcCemuP+X+78+vQ4kaM8Kc9zvXDB1ABb4ADWNRBT8k0o9Mlzk2Y5y8oXWeN+TYmYQkW8ZmEeH66gwp4A3SwaJWm3NQWlH6VsgZR/MxQ0LcAs8Q/O0xZ3RLDeQMscXE8tTUoEIy+jzALM9bmPoI3WEW34C+1JbiaT2Ucz8MXpIA3wIKE92H7U8AEukzQwf3N7mvWc2O/DrkEBrdgmPf2heInlVIBb4ClLIsntUYF6qrRdG5/NytQoR9SWmKNWYIIt2CEfyqQiw+dUAFvgAkF9NNzVKCxbHeydmOOEScKFZvfzZ1fh3bZLRiZ/KOJJvh/L5cC3gDLVQ/PZhwFTKDTBJ1SYpG+LvJctHhbiTl6aiso4A3QLwdnFGBgvwdg57ITFjQXYe2MsvP0/ABvgH4VuKFAXa+l0c/cIAsIPAQhv+oK36ry9AZY1cq7lnegIwld4A5t3qeQ27rDt5pMvQFWs+7OZW2CqCUwcIm4JnEKLudjLnGuGldvgFWruIv57qP1uJ5+CeCVLtEXo2loTVriEueqcfUGWLWKu5hvQ+8i9Z+uUfcGWP6KeQMsf40qz9A0orNEnuCaEN4Ay18xb4Dlr1HlGTKwdwPY3jEhnlVo1neMc+XoegOsXMkdS7iuN9LIvf23wtfUNnXH1K4cXW+AlSu5Ywk3omMY765w7BL4foS81DHalaPrDbByJXcrYTbsN0Ds7xZrQIabYJhPuMa7any9AVat4i7lO11/w3U63V/+xiXaIP5bLePaM0unJE6LrDfAtJT0OOkrUB/dn8Z8I33gbBEpftK2+fFso3j0NBTwBpiGih4jEwVMIzpX5DGZgGcIKnAnhLwjwxAeOiUFvAGmJKSHSV8BBjZ++/vG9JEzRfyDQvOKTCN48NQU8AaYmpQeKFUFZmo7Rvp+qpg5gBG6woa1WTmE8iFSUMAbYAoieogMFGjqBEpnZYCcKaRoD0JraHGmQTx4agp4A0xNSg+UpgIMbLz3911pYuaBpef5clzJP+YRy8dIroA3wOQaeoS0FZitjblUvwawbtrQGeP9l0LzTxnH8PApKuANMEUxPVRKCjQVUGqlhJYbjMBTEfJTuQX0gRIr4A0wsYQeIG0FTFPnS/pA2rhZ44l8G1r8YdZxPH56CngDTE9Lj5SSAgxsfPbHa1OCyweGeEwtMyWfYD5KWgp4A0xLSY+TjgJN7UwpPv3NqYvgJTbk4U6R9mT9qXB+DZRMgaZOpuTcczSBByCkc9v2Slb93On4X4C5S+4DjqcAA3sjgN1dU0n2kfUwstlzrvGuOl9vgFVfAWXKv6nNKP2mTJS65HKzQrNbl2P9sBIp4A2wRMWoPJWmZlNy7jBxSR9Fu/aZytfPQQG8ATpYtEGlbIJoocD3uZafLN+AEf7UNd6eL/xLEL8IyqMAAxs3P92iPIy6YvKgQrNlVyP9oNIp4H8Blq4kFSXU1K6UbnYte0Ln2bB2tGu8Pd8xBbwB+pVQCgVMEM0X3OuiLPI9aNG5Q9tLUfQSkPAGWIIieAoAA90CaKpjWliFHAIox3h7ussV8Abol0LxCgR6NaFfFE+kVwa8XiGda9nVa5aDPN4b4CBX15XcgtHDCXORK3Rf4CnwQwj5Rdd4e74vKuAN0K+GwhUwgS4XdFDhRHokICzdGuG6D/Q4zQ8vkQLeAEtUjEpSqWsyTaf56SaO5f9zheZ1jnH2dFdRwBugXxLFKtBYtidZu6FYEr1Hp3S2bdeO732mn1EmBbwBlqkaFeRiAi0Q9DHXUpf4TrR5k2u8Pd+VFfAG6FdEoQowsPEB4jsWSqL34M8qNOv3Ps3PKJsC3gDLVpEq8Qm0DSEX99BeqdDsX6VSDWqu3gAHtbIu5BXog4S+5ALVFTlKnIM2nftsxzWd8+DrDTAPlX2MNSrAhh0BcaBr8shyU4zwEdd4e76rK+AN0K+KYhSo66U0ehjAy4oh0HfUexSat/Q9208slQLeAEtVjgqRaWgfUle7ljHJBbbFk13j7fmuWQFvgL2sjLpeAYNdAUwB7BBo7kKEezHCp3uB8WMB04g+J/I417QQo6loTbqtFLz31QZYb3Q7WLMdgGdA8xgsbsMInywFPwdIeAPstkiBDiIwF9AbVpnyG4GnI+SXu4Xy4+LuLzY+QNy1W8k/KDSvKEX9Ah1JKP4luvnKfHifgAUIeUUpeJachDfALgpkGtGnxPFve0i1basWdAHnh9T1FhrFBujURSi0Ya1ZNGnTjEKJjfF4UDrdtmunFM217PG9AU5QIRNE5wj8cDeFJLnQtnhYN2MrPSbQsYTOdk0DwR6CcKjQQ5t6OTeF0Lk2rB3rms558vUGOI7aJoguEnh4LwUh9AUb1o7pZU7VxrJhrwKxr2t5y/DvMMzfF8XbBPq8oA/1Ep/QxTasHdHLnCqN9Qa4pmrXVTMGXxU0s5/F4N8UjqPa/tqIkxV/Q7dOP9oWNoe4Sy1T2Ja9JHumCS62IZ1rN5ZHrb0Brqry+7UBn9EiAPslKYCgUxHWPpUEYyDnNnQAqa+5lpvEeWhzfiG8G9GpJD+ZLDav0mQchEV8JhnOYM32BrhiPevahKZjfrunUWaBxyLkuWlgDQqGaURfFOncKWoCd0DIu3OvQ7rPS2+S5WyM8PHc8yhpQG+ALxQmPpdCWgRipzRrJfJwtHhJmpguYzHQ/YBcayT6uELzqtx1b+gIUhemGpe4XeJshPSdrP2xmMuX1gy9ibbzy+9NqS625WACZyBkKwtspzBnagdGutMpzvEfCXmZbfHQXHk3R2dSJqtv+e6V4WwM895ccyphMP8LsL5sJ5r40wZtnWF9JNn90B66JsMY5YduRidRPKP8RFdmKMMAw2znxrupfSldmfEPlAeW3w7fnlteJQxUbQNs6l8JLIKUx+3NU7LRdIxM+m4J10EulNjU9ZD2yiVYikH0HDfE1XwqRci1Q8Vrcsz8XppDvMc7t8MV7mxdXQOM/5e1uhzEBjkstBdCPC6OTkdrsnO3gYk1mqVXcZkeTYyTP8BtCk0+B7YHegehb+Z8QNSfBXswwqGr8pe2+IjVNMCGZpC6HIApoAS/kOF0DPO+AmIXFzLbZ1qZ5SVoLsJa9rftgbYlOr/8Xp1ZMmsHjkR7MFpDiwuIXWjI6hlgOQ7hvkfkdLT4YKHVzzG4aepCSc7tSJDhmzN/WVDXljQd88vkJVy3ZRZ4BEJe3O34QRhXLQMMog8TPKckhfueLPfHCH9XEj6Z0mBgY7P/h0yDpA/+oEKzZfqwKyDur405Gd8EtHOmcboEr9q3q9UxwIbmkjq9y3WQ0zB+S8/ivbiGz+YUsJgwzWX/QtVuLSZ4/1EJXWjD2pH9I0wwc47W4x91JYh3ZhajD2CRp6DFkv2t9JFIF1MqYYAm0GmCytoa6BsKzQFd1MrdIU39O6X/cC0BgdMRMrOXAwxs/MJjehl1qUo7rYE3QBPobEGlbglEaJENaweX8Q8hDU4M7M1Ap5O2S1ekl/EluJDLsiBtmlokaVYW2GlhVqGd1kAboGlGF0p04sE7pQtsu3ZUWou3NDjN57ag1vlVafh0S4S8US3u0e3wXsaZILpAYHa31r2QmWDsoLfTGkwDnCdj7reLBPbVzirF9dMTFKHP2rB2Qk+Tyj64qUMpXVp2mqvyE3gcwvRfmJkg+qzA413SY5DbaQ2eAe6rDfiS5O2silqgJOfbFucVFT/tuCaILhPo3O297NLXYWTdn6ephwk0X9DH08TMD4tXKWQpn1cm0WCwDLD+9CY066XWziqJsEnmCjwRIc9KglGKufP+/y7a+zu7P15ZCj7dk/i5QpNux5qGTiR1ZvcUSjnyJoWmVG+sk6o0OAY4U1txtLO1LdV2VkkF7ne+wKMR8rx+55di3ti+1ptKwaUHEqkfa9CIjib5xR4olHdo3E5rEt85KI1VB8MA63ojTWdrW6Ff0qe9aiUeijYvSxs3LzwTRKcJLOvnR2uVQYZ7Y5g3pKLTDB1Cq6+kglUekHs1iXvhcj5WHkr9MXHfAMc2kMfmV8Qeyv5U72FW1t+i9UCl56EMdDugd/Q8scgJwrNqm/VToRBov+X7e1OBKxnIAzJ8D4b5s5Lx6omO2wY4dosVm98mPWXt1GDeKYupGOFSp2gH+kdCqb5EyCn/axWafRLHqmsyDW4FVNhBSolzmBjA+e5G7hpgfXRfGhObX57trCZeEhmMkDQf7Zpbb4abmkPpyxnIkSmkwA8i5PmJgzSieSQ/kRin/AB/luGBGOaN5ae6OkM3DTBQk1DcLryIdla515nkRbbFObkHThDQBNGwwGYCiEKmqsYtsJi/ThrcBNF5Agfvw/Y1CxO302qiNeTcaX/uGWBTh1GqVMseCP+ptnlP0j/K3ObX9RIaxSePbZhbzHQC3avQvDkNKFcPf0+Su8jD0OLCJBh5z3XLAJs6hlLljpkkNWxbNXd2tQTam9B1eS/mpPEInmVDnpgUJ55vAl0qKN+DlNIgnhDDtXZa7hhgI5pLVqNFz6prUOTxaPHshGszt+kmiD4t8KO5BUwpkBTthvakuHFD8qupD1BK/iwxOZPcEVxqp+WEAbr6PVlKK+/3Aqch5E9SwsschoH9EYBUbiUzJ/tigCcVmo1SixfozUTnI/C/TQ3TISBX2mmV3gBNEJ3d+Vld0UuMdkdr0necSX/sbIsfO8P3RaJfV2gOTJV3c9muVC2dX5SpEssHzIV2WqU2QNOILhTdaGeVxZLK7UCeNMkH0YcIfj5NyDywJHsY2kPpP8BvLt2eGro7jxzKGKPs7bRKaoCiCezlrrWzSnMBCnYGwqFWmph5YJW5y/F4+cvyVRhh/OY6/Wt/bcTJ+n36wG4glrmdVvkMsK6XLt/Xu58b5U2fpcCdEPKO9JEzRqzrZTT6LYDJGUdKF564Sy2T+Y4NBjb+vnDzdMm7glbOdlrlMsAZemXnsHJgd1fKmjJPyXJKZr9EUia7GlxjdDpp4nMunLpInmZb/Pc8SLOpJZB2ySNWCWOUrp1WeQwwbmcVm58Go51Vz4tPeExtM6XneSWaYAKdI+jDJaLUFRUZ7oxh3t7V4BQGmWb0FYmHpADlHkTcTqtlSnEEaCxeOQyw/vwbaSZfDmig2ln1sDrvVGjc6pqyhuQY2LgzyGt7yLv4oUX9x9PQJ0i5tb87vWqltuMmKaXiDbCpHSktBrBV0mRcnE8otGHNuT2zq2ld13Y0+r5rNSB4hQ1ZzOlsjdFDSDNovQK7XQIPaDLfXHRj1WINcIZ2o+2Yn2st07st8rjjKJ5p2/xYKmBFgzT0EVKfKZpGr/EFOwvhUNxYo5iroamkbikmeOFRH9ckvq3IxqrFGWBD+5Ad83tp4WUogIDIo9DiBQWEziQkm7oe0l6ZgGcIqhpfgcX8Q4YhJoaua2sa/c/EAwdyRNxOa8eiGqsWY4Bj7axi8ysmfsHrSLDvQjh0fcE00gu/vzbmZD2RHmBuSLcpNFNzizZeoLFPiH5R0a1zkTj6T2hNvjPvWuRvQM3RwyhTrXZWL1bVCtwWIe/Pu9CZxmuoQSrMNEYG4JL+He3aaRlA9w3JwMa7RrbvG8DhiTLcI+/GqvkaYCM6hmTl2lktX5OPynJrjPA5h9foGqmbRnS+yA+4lpfA7RDyB2XjbQLbFlAvG688+Ii2nmdj1fwMsKG5pE7PQ8QSxviBQrNdCXmlQsnRHQ4PKjRbpiJABiAm0JmCUulNmAG9TCHzbKyaiwGaQKcJcu54xFSq7Fo3516TrmsnGv1Xr9OKHk9yoW3xsKJ5jBs/iI4iHD8buk+BRR2PVi3zHpiZG6AJdLagSrazInShDWtH9rkG3JjWjE6m+Ck3yL7IUuKBaPPrpefdHN2XMleVnmcGBCXOQ5vzM4D+K2SmBmiaulDSEVkmUFZsiSejzQVl5ZcWLzbsEhCu7W0dleWGzjyPHTv7OretemmtjTRwKJ5t2zw+Daw1YWRkgKJp2CtEzsiKeJlxJc5Em8Nl5pgKt4O0KUf1UCpY+YKUblP+hOkHevXyRrMvmXDsgA2gtNC2a5k8rkjfAON2VtQVIPYdsDp0k04kRlPRmuTcM7FuklttTHN0NmW+2tfcAid1Xi6EtbMKpNBf6IO0IUc7vwRf3x+Aw7PEr6nN1N+Mp2uAs7Uxl3Y+cP5Xh6Xul/ojIndAi4/2C+DaPBNElwp07uQzmWXbYnid+1zT+wW+bOpaSO92lX/fvIUb1TZ79D1/DRPTM8C6tqTpmJ/zXU16F5jfV8i39z7P7Rls2icgbOxYFj9TaLZxjPNqdE0j+qLIo13Po2f+KbfTSscAxw7Cic3vjT0n5P6EaxWafdxPo8cMZmgXWi3pcVbhwwmdb8PaBwsnkgaBpk6idEYaUI5hpNZOK7kBVridVdkPfMlyUZum5kn6RJYxssAWuA9CXpsFdiGYDb2f1CWFxC426AMKzdZJKSQzwAq3s6L4Sdvmx5MWwNX5DGx8Zknm52ikrM8z2oYbYh5tyrjFwjVG9yHN1cWSKCT64wrNq5JE7t8AK9zOStDRCGvnJRHe6bnx8QWRHnAwh8F9XDF2J+beQVrJF9GfNZlT+m2s2p8BjrWzGvzv3FYvzqjE/dDmdcnr5jBCU4dRcq6jj8BjEPILDis/PvXOf0z4DqAtBjbHNScWaRI366exau8G6OjiT7wghIcl7okR/jQxluMAJtCwIOfa+AvcGiFd/OXa/YrZVxvwJYpvh3ftftJgjJThNr02Vu3NAIPowwTPGQy5esmCd2sypvX7M7uXSKUfO0eT+KfOId8blp7rygTvUWje4hjnvumaQJcJOrhvAEcniqPv6KWxavcG2IhOJt3b9J5CHa9RaKq4q2XN0gXag9C3UtA1VwhC59iwdlyuQQsOZoLoMwI/UjCN3MP30li1KwM0jehTIk/OPZOCA1K6yLZrcwqmUarwJogWCO4d5CQb7YGRSTeWSsw8yDR0Iqkz8whVphjdNlad0ABNEJ0j0LnDrpMWg+B/2JDOfeeWNO+J5jOw9wBw7fzmJxWajSbKbWD/PdD7CC0c2PzWklg3jVXHNUATRBcJPLxywkEfRFg7v2p5T5hvoG0IufgS6OsKzYET5jfIA4LR9xDmmkFOcU25TdRYda0GaJrRYqly7ayWSWygzSurtlC6yjfQUYSc+/5R5JFo8cKuchzkQTO1AyPFu2D+bpDTXDW38Rqrrm6As7U+n8diUFV78P+QwAZCVvFj0q7+HhjY+D+G/boaXKJBGuJmuIIPl4hScVTGmpa0q3by3Noaq65sgJ12VlgMqFrtrMi7FOG9GOEjxa3MkkeO+zwaPQlgUsmZrkxPuEtt49qWvWwljn/kLEUb0LuyDVQu9DU1Vn3RAMf+Z4h3d1RrsQhXq22c+1WT+9IK9B5Czj1DIniGDTk3d70cCGia0VckHuIA1fQortJYdcwAm9qC6izubdOLVH4kgl+2oXvn2RahrAmiswU6d7iVyKlo8bYiNHMhpmlEZ4k8wQWuqXFcobFqxwBNoEsFOdfZN4kgJOfbFuclwajSXAb25wD+0bGcH1Vo/t4xzvnTDfRRQp/OP3BxESWdhHbt00Rz9FDKXFoclfwjSzoK7doF+Ud2NGKgNxP6kWvs4ya9Nqwd5BrvQvg2dSilivmAnUkT6KuCZhciev5Bly5/01vJc1b7ljuIjiWY+SHVffNby0TJHor20GVp4w4sXn303aRpg1hvYHNcITECI2RgfwWgCu1zfiOygRbvrEJx08yRgb0BwJ5pYuaBJcuNMcLf5RFrYGIEejvR+Uxm8D1BeNgb4MCs3IwSqesVNPrfjNCzhL1VoXHtwPYs9egOu64dln8n+A/dTXB4VGyA/hbY4QLmQb0xegBpvpZHqDRjkJpvWzX/kqsXUcc+dRoBsG4v01wd27kFRgU3SvuXIN0vWdPU+ZI+0P2McoyU5Y4Y4V3lYOMAiwo2Ohbt+5Z/BmPbAlI/db3MZfefwXRXHQb6NaDNuxtdmlG/Umi2Kg2bshOpYK9Pgl+xIccMML4Y2LjJZaqnrpe97v5D6AkqVF+6A82Qcy+NSC60LR5W9vVXBn4m0DmCqtbu7ici90GLD660F9g0o7DTDaVKl98Kt/ZqN6KTSDp38LbIJloMq7SM+8nVBNGwQOfOdukn1xXm3CnLGRhh/PULVusGYwJdIOjIhEHcmu6bIayxXgzsLQCmOlbMZVofG2Ehn3KLd45sD9ZGnWYI0m45Ri0+lPBdrcMZWMTf/vXOd02sTCM6Q+RJxTPOlYFvh7Wi3HVtQqPHcq1AGsFW2OeZBtzAYdT1ehrFb/W3Gbjcxk/oGk3umN8zKw5be0fopk6i5NztT8Ki+oaoLwjY0AxSixPqmft0SSejXVuQe2AXAjaWTSNr1wNYxwW6aXEkOWxbnLkmvPHPBAmiIwlWbs+sfEt8uNoqSeBbEDI+t8RfKyrQVECpVTVRCF5sQx6xtrwnPBQJDTVIVe6BctUPRWJg4+ckjrVO5/0K+fqq/ZFPmG8jOobkuROOG7ABBM+14fgt3CY2wFgUR8+CTVrPyh6LWdc/08i5HnqEzrdh7YNJ6z5I802g0wSdMkg5dZMLxdNtmxPm3Z0BjplgvEm6il/WV+9g9Eb0CdK9XokS9/cHWr1oD5U91ZE8BS2e3pVRdjPor2Nm6jWM9H97mjMQg3m3JmPaqm+QBiK1NSTBpr0Twg6O5fe0LDfCCJc6xjt9uodqXT6Hr1ftzI9YyE7X8rD72/3ufwG+UKamplCq3uFBwsMS98QIXTwXt/s/spn6B0Z6sPsJZRnJaxSyaicZri5+XZvT6NsAXluWyuTFQ+ARCHlxL/F6N8AYfaZezkjxQ/KhXoINwNhRifuhzesGIJc1pzBDh9DqK67lJ/J4tNxr2pqqzmOPqb7n3Ml9KYggcSbajA916+nqzwDjEHtrHW6IhwA59qawJ33WOFjQ0Qhrzh0Q3k3mJlBLUNDN2DKNkeXrMML43JJqXk29m+ocel616xmRM9Hi1f0k3r8BLo/GwMbPBF/TT3CX51D8pG3z4y7nsBr3eTK8X38EsIFjef1IoXmrY5zTo9vQ+0ldkh6gI0jCb2U65vedfhknNsA4MAMbvx1+e78kXJ1H6GIb1tb6kaVzec3QbrTqezEVlS/Js22LxxcVv9C4jWgu2d0bz0J5ph/8VwJnIuQdSaBTMcDlJli5dlrLhb9WodknSRHKMtcEWiDoY2Xh0y0Pwb4L4VC8xatSlwmiLwms4nePP5HlTIzwx0kLnpoBxkQq2U6rUwF+XyGd/wXMQPcAelPSRZXrfOF/1TZ/m2vMEgRjw14PYq8SUMmbwp2qcSYW85dpBE7VADsmWMV2WmOVeETkDmjx0TQKkzuGq994Cl9T21Snm/nYIVW3O3hIffIlTXy388JjmE8kBxtDSN0AOyZYzXZaceqRGE1Fa9J/pVWg3HAcbXwh8GiEHMg38qvVPtA2hO6t4OdnsRTXLL/tfTrNv4lMDLBDsJrttDqp9/tNUpqF7RWLDXsVCOc+JBa5ZdzavNd8nRs/Q7vQaolzvFMgTKhlQzMToFKAWwkiOwOMwzj6qyINkSWejDbd6EvX2TqluIOyax+236nQvCONepUao6IdmcZuUXWJDWuHZ1WfbA0wZl3t4l1ow1r5jxcIRvcmjHO7WwieYUPOzeqPoxS4TZ1A6axScMmZBKXP23Yt0wObsjfAWLT66LtpTBW/Uo93Z/+n2uY9Oa+dnsKZIDpHYKYLrSdCXQ6WuBvavLnL4c4NM4HOE3SUc8RTIExqgW3VTk4BalyIfAxw7JfgNFLfzTqhkuL/QKHZrqTc4g/ZHdzNw0cUctOyapqUFwPdAGjPpDguzhd0KsLap/Lgnp8Bxtk0tSOlRF9u5yFKRjEeleXWGOFzGeH3Bxs8vy0xKfEHpf0F738WoStsWJvVP0JJZ9Y1mUb3Adi6pAwzpSXoOIS1czINsgJ4vgYYB56hN9HGH9xW8rICt0XI+0uTfaAPE8ptwaWVt2gPR2tosPa/NrUZ1WlFZtLSySUcyc5Be+iiPDnnb4BxdnVtTaPYBFx765hKbcq0dYuBdXILo5ZxCr5B947tXNsKai7dnhq6O5UF5h6IRDsLraHcTyEsxgDHboenUPhRFdtpxemLPAqtgk/cqz/5Mpq/ibu/uHWRt6jFXd0iPQ7bhg4gO2f1VvF6WrCzEA5dVUTyxRlgnO1YY9U7q9hOK06f4pm2zeKaDwTaj9CVRSy8JDFJzbet2rwkGKWZG+ijhD5dGj75EnlCimahPemmfMO+GK1YA4x5dBqrdk4gc76ZQD9FJBTasNbsZ27SOa7u2xb5T2jRve2GqxTMBNEFAsv/nWjShbbm+b+UjWZhZFK8r7mwq3gDXJ66q8+iUqpcITsaGNjfANgspRzygvmlQvPqvIJlFYcN+20Q78wKv9y4/LHM0lkYXife11zoVRoDjFWobjutznFWj6ltpuS2GgK9jdB/5xYvpUAEL7EhM9salRLNcWEY2F8AcN7E+9OKdwjPz0K47gP9zU93VqkMsGOC1W2nFacvWU7BCB9Pt8xrQHO0WYXAWQh5Reb6ZBFg7Jn3/2bVhSkLyqliCt/t9PJLsZ1VUn6lM8COCVa3nVanngJ3Strqe6KFwUC3AJo60biS/fsy1fhKLOYfSsZrYjr1pdvRDH00GtgFAAAOa0lEQVR/4oEDOyKTdlZJ1SqlAXaSCqJTCJ6WNEFX5wt2BsKhVib86/o7ms6xpq5d31Zo3NseFozWCdN2Tey0+GbZziopx/IaYJxZU8dR+lzSJF2dL2guwtoZqfNvjgaUycZcUyf7IqDAuQiZvh4ZckYzOolyjHOKemTdziop1XIbYOeXoI4kdEHSRF2dL0a7ozUp1ZPaTBBdJvBg1zSR5fYYoTsvbpqaQ+nLrumcFt882lkl5Vp+A+yY4OjBhLksabKOzv+9wGkI+ZO0+DOwvwPg2kFC9ys0r09Lg8xxmkvfSg3dCuClmccqYQCSC2yLmbezSpq6GwY4djt8IKWRpAm7OF/k8Wjx7FS4B3oH0TlUx6mL4Hk25NHOkG7qA5TOd4ZvikQFnoqQubSzSkrbHQOMM61oY1VSw7ZVm5m02PF804zmSfxEGlh5Yoiso0Vn9suaQJcKOjRPjcoQS+BxCOlMdyG3DDCucBUbq6bYVZqBvcvBbYdP6Vlugmv4bBn+yLvh4OohU93ktrYxIuegxVzbWSXhG891zwDHbofjxqr/pyrttEheZFuck7TYqOvvafRwYpz8Aa5RaJw6sc4E0XkCq9LO3oqcjRZzb2eVdCm6aYBx1p3GqripCu20JM1HO4XuJw0dQuorSRdN3vNTfQaaF/lGNI9071FDH/I8JXA2QhbSzqoPvitNcdcAO88EO41V49PMXpNUiPLO552ymIoRLk3K0dW91jLcFsOM28S7c3Va2+NWQDu6Q7pnpk9InIU2C2tn1TPjVSa4bYBjt8NTqE5Pu4FspyVwelr/uzKw8dm/jn2WwR8q5NuSLvRC5jvab7FLrX4pw1kYpnNfFKyYn/sGGGcztsk83tmwR5fFc2KYxEPRZjrfP9a1C42WOJH4CiQpnW3bteNd4/1XvjN0CK17jx0m0PvHy82v8HZWSdfFYBhgrELcWHUDXQ7iwKSilGG+wKMR8ry0uJiGzhB1Ulp4eeFIdl+0h67JK14mcRrR0SS/mAl2/qB3LO/IU4p2VknTHxwDXK6ECXSZIOe2ea1YSIEnIuRZSYu70k/9wMb/W78xTcwcsH4vy00wwiiHWNmGaOhEUmdmGyRz9O/IclYu7doyT2UswMAZYJyUy63GSc63LaZ73sUB2opDcu5/bIIjNmQjp7+FzMOYQPMFfTzzQFkEEK7WXzgLVzN+jjww10AaYMcEG9HnRB7nUqUIfdaGtRNS5+xoQwlBRyOspfYYIHVd+wA0QfRZgU490yQ5bF+HWZhH20fKpZ4ysAY49ktQpwk6pdQVWE6O0gW2Xcvkw1k2dRUkpz4kjmWR5Wswwrh9/EBdLt2hELzYhjxioAqwQjIDbYCdPB1orEpokQ1r2Ty3nKNJ/JPiLWSuHUJ/h0Kz06D+4ZmmFkmaVeb8CJ5rQx5bZo5JuQ2+AcYKlbux6jcUmgOSFnKt8xvL9iRrN2SGnxGwK+2UkqTPwH4TwPQkGFnNJbXAtmqlb2eVNP9qGGDnl2AZG6vyW3oW781yk79pROeKPCbpQsl7vgz3wDBvzDturvHmaD3+UVeW7XhMQacirDnRzippvapjgB0TLFVj1e/Jcn+MMG5OmtnFwP4PgK0zC5AN8CMKzabZQJcMdX9tzMn4JqCdy8BM0HEIa860s0qqWbUMcOx2uAyNVe8ROR0tPpi0gOPOn6HX0er+TGNkAE7qctuqzc4AupyQdW1J09nO+aYiCUp2DtpDTrWzSqpX9QwwVmyssWq84Ip4MfALGU7PZXN/EB1LpNRJOulK62G+yMPQ4sIeprg/NNC2RMcEizgw3dl2VkkLX00DjFXrNFZFmHM7rcfF0eloTb4zaeG6mc+G/XbZni91w1vk5mjxoW7GDtSYseMK4hcjm+SYl9PtrJLqVF0DHLsdjhurXp7TM7KnZKPpGJn03aRF62r+bK3PpXq6q7FlGiTcorbZtUyUcuXS1L8u726UR9eexyXOdrmdVdLaVNsAY/U6jVW1KOPnL5Lsfrlu6ne0FZPEeWhzftKF7fT8pvZdboJZ/n0+IMPZrrezSlrnLAVOyi2/+WONVeNfgpk0rxQ4AyFzPYjcBNGXhRTa6OdXhU4kibugzfg4yWpfzdGZlLkiIxHuXW5+zrezSqqPN8AXFBxrrBqb4LSkoq44X+ThaPGSNDG7wWLDPgTCsU9J+IBCuvbJTjfl6G9MQ0eQurC/yWuZRdyuaOnBGFl34LYY9qOTN8AVVYsbq1osgvTufsRcdY7AYxHy3DSwesIYu62/p6c5JRhM6BIb1g4vAZXyUAh0LKF0zoQGb9IyHIxv8LHyJFgsE2+Aq+qfUmPVQr+mD/QxQguKXVq9R1/eaDOr277eCZVlRiM6leQnE9GJ21lN4mxcwT8nwhmwyd4A11LQJI1Vi97HysDGz9D+xbG1ulRLn9kM39zgt47xzoWuCbRA0Mf6CUZq2EZm9kA0lu1HgHHmeAMcR5x+2hYR+oINa8XtvR07H+XJlNdJDnD8lkLulUMgZ0OYQJ8X9KFeEiB0sQ1rA9vOqhct1jTWG+AECvbSWJXkQtviYUmLkmh+UwHVOSDKqUvQXIS1M5wiXQBZE0QLBb6vm9CEzrVhbaDbWXWjw3hjvAF2oWA3jVVJtW2rFnQBl+mQJLfumRKbAFzkO9BiLjtkiswzjdjdnO9M6XTbrjnRDDgNTfrF8AbYrXKBDiIwF9AbVpnyG4GnI+SXu4XKchwD/Q7Q32YZIwPsnyo0q+qaQZgBghxr7xb369t85ax4n4AFCOlfJnVRbm+AXYj01yF1vQIG8TatKYAdAs1diHAvRliOLWfNpTtSQ3f0klIZxpL8km3x38rAxSkO+2oDrDe6HazZDsAzoHkMFrdhhA4+Ay5GeW+AxeieSVQTRPMFOnfqmGjraA19LRNRPKhXYBwFvAEO0PJgYO8GsL1TKQlPaRI39d+nOVW1gSHrDXBQSlnXJjRy7wv/+APdttlvUMrg83BLAW+AbtVr7Wybo4dS5lLX0hF4HEJWpgW7a/UZdL7eAAekwiawbQF119KRHX0rRib/yDXenu9gKOANcDDqCAY2fhO9vmPp/FCheZtjnD3dAVLAG+AgFLOuXWi0xLVUCH7OhvyIa7w938FRwBvgANTSBNGZAk90LRWB+yDkta7x9nwHRwFvgANQSwb2xwC2dSyV3+nP3AzX83nHeHu6A6SAN0DXi1nX5jT6tWtpEBixoWm4xtvzHSwFvAG6Xs+mPkDpfNfSEPhBhHSOt2s6e77jK+AN0PEVwkBXA9rHtTRkuA2G+TPXeHu+g6WAN0Cn6yky0DIANafSIG9Xizs7xdmTHUgFvAG6XNaG9iR1g2spkFpgW7W4lZO/vAKFKuANsFD5kwU3TZ0rqbj2+33Sl+EeGOaNfU7307wCqSngDTA1KfMHYqD/AeTWObrCw2qbzfJXy0f0CqyugDdAV1dF/S+vpZns3EsEgotsyINdld3zHiwFvAG6Ws9GdBzJz7lGX7KHoT200DXenu9gKuAN0NG6MrDxM7TdXaMvy60wwl+5xtvzHUwFvAG6WNcPaR3+Vn9xkPoShWaag7w95QFVwBugi4VtjE4nzTddoy7wEwj5H67x9nwHVwFvgA7W1jSiC0Ue4Rp1KdoF7Um3usbb8x1cBbwBOlhbBvZhAH/vGPUHFBq3PtlxTGBPt3cFvAH2rlmxMwK9mZBzLeQJXWzDmnO/Wostto+etQLeALNWOG38huaSOj1t2KzxRB6EFhdnHcfjewV6UcAbYC9qlWAsm/Y2CP9cAiq9UHhefG4rtNZ/tJdJfqxXIGsFvAFmrXCa+AdpQ47qT2lC5oT1LYVmr5xi+TBega4V8AbYtVQlGBioSWi4BEx6oiDyY2jxzJ4m+cFegRwU8AaYg8hphTCBvipodlp4eeGoxh2xmHflFc/H8Qp0q4A3wG6VKsE4Nu3vIWxUAio9UOB9CunagU095OeHuqyAN0BXqtfUjpTucIXuCzwpfcm2a//mGm/PtxoKeAN0pM4m0HxBH3eE7l9pSjwQbX7dNd6ebzUU8AboSJ0Z6G5A2ztC9wWaf5bllhjhk47x9nQrooA3QBcKPePpV9Ku97gLVFfmyKsUcrp7vD3jqijgDdCFSgej7yOMc01EBR2HsHaOCxJ7jtVUwBugA3Vnw46AONABqitRFPgWhLzHNd6eb3UU8AboQK3ZsM+AWM8BqitS/IFCs51jnD3diingDbDsBW8u25Wq3Vx2mqvyI/hZG/IE13h7vtVSwBtg2evtqAEKdh+EQ9eWXV7Pr9oKeAMse/3dNMDfaTK3xCI+U3Z5Pb9qK+ANsOz1r2syTacDzLplp/oCP1Jt26oFrvD1PKurgDdAB2pvgugywZ3DxEUehRYvcEBaT7HiCngDdGEBOHYbLMNtMMyfuSCt51htBbwBulL/RvQRkp8pPV3hdrXNzqXn6Ql6BQB4A3RpGTT1L5Q+DOCAstKmdLpt104pKz/PyyuwogLeAF1cD3W9BbTTCLMroGkgNihLGhLfiTZvKgsfz8MrMJ4C3gBdXx8z9XKMYjcDO03krgDeUGBKD+kJboUlHC2Qgw/tFehaAW+AXUvlyMCmtofFbhz7ZRgbYm6fzxBaZMPawY4o5Wl6BfwzwIFeA3W9DCba26A2TbEhAq/JMl+B70fIS7OM4bG9Amkq4H8Bpqlm2bECvQ2wexNmWufZIWDSpCxyS7T4YJqYHssrkKUC3gCzVLfM2PtqA6wb7W3IvQTGZrhFErqkFthW7eQkGH6uVyBvBbwB5q14WeONvVnem4wPMNfU3mjyh7KYihE+3ds8P9orUKwC3gCL1b+c0WdrfTyPvQzt3gL3BjBl7UR5k4j3o8WHypmMZ+UVGGf1enG8AhMqMENvQhT/OuReADYDsCnImyVcDYtLMMKlE2L4AV6BEirw/wBT9ySzG22TjAAAAABJRU5ErkJggg==", + "width": "200", + "height": "200" + } + } + }, + "h1": { + "name": "h1", + "label": "大标题", + "categoryId": "html", + "snippet": { + "children": "标题" + } + }, + "h2": { + "name": "h2", + "label": "中标题", + "categoryId": "html", + "snippet": { + "children": "标题" + } + }, + "h3": { + "name": "h3", + "label": "小标题", + "categoryId": "html", + "snippet": { + "children": "标题" + } + }, + "p": { + "name": "p", + "label": "段落", + "categoryId": "html", + "snippet": { + "children": "段落文本" + } + }, + "component": { + "name": "component", + "label": "动态组件", + "categoryId": "elements", + "doc": "https://cn.vuejs.org/api/built-in-special-elements.html#component", + "props": [ + { + "name": "is", + "label": "组件名", + "setters": "InputSetter" + } + ], + "snippet": { + "children": "组件文本内容示例", + "props": { + "is": "div" + } + } + }, + "slot": { + "name": "slot", + "label": "插槽", + "categoryId": "elements", + "doc": "https://cn.vuejs.org/api/built-in-special-elements.html#slot", + "props": [ + { + "name": "name", + "label": "名称", + "defaultValue": "default", + "setters": "InputSetter" + } + ], + "snippet": { + "children": "默认插槽内容" + } + }, + "Transition": { + "name": "Transition", + "label": "过渡效果", + "categoryId": "components", + "doc": "https://cn.vuejs.org/api/built-in-components.html#transition", + "package": "vue", + "props": [ + { + "name": "name", + "label": "名称", + "defaultValue": "", + "title": "用于自动生成过渡 CSS class 名", + "setters": "InputSetter" + }, + { + "name": "css", + "label": "应用CSS", + "defaultValue": true, + "title": "是否应用 CSS 过渡 class", + "setters": "BooleanSetter" + }, + { + "name": "type", + "label": "事件类型", + "title": "指定要等待的过渡事件类型来确定过渡结束的时间,默认情况下会自动检测持续时间较长的类型", + "setters": "SelectSetter", + "options": ["transition", "animation"] + }, + { + "name": "duration", + "label": "持续时间", + "title": "显式指定过渡的持续时间", + "setters": ["NumberSetter", "JSONSetter"] + }, + { + "name": "mode", + "label": "时序", + "defaultValue": "default", + "title": "控制离开/进入过渡的时序。", + "setters": "SelectSetter", + "options": ["in-out", "out-in", "default"] + }, + { + "name": "appear", + "label": "使用过渡", + "defaultValue": false, + "title": "是否对初始渲染使用过渡", + "setters": "BooleanSetter" + }, + { + "name": "enterFromClass", + "label": "enterFromClass", + "setters": "InputSetter" + }, + { + "name": "enterActiveClass", + "label": "enterActiveClass", + "setters": "InputSetter" + }, + { + "name": "enterToClass", + "label": "enterToClass", + "setters": "InputSetter" + }, + { + "name": "appearFromClass", + "label": "appearFromClass", + "setters": "InputSetter" + }, + { + "name": "appearActiveClass", + "label": "appearActiveClass", + "setters": "InputSetter" + }, + { + "name": "appearToClass", + "label": "appearToClass", + "setters": "InputSetter" + }, + { + "name": "leaveFromClass", + "label": "leaveFromClass", + "setters": "InputSetter" + }, + { + "name": "leaveActiveClass", + "label": "leaveActiveClass", + "setters": "InputSetter" + }, + { + "name": "leaveToClass", + "label": "leaveToClass", + "setters": "InputSetter" + } + ], + "events": [ + "before-enter", + "before-leave", + "enter", + "leave", + "appear", + "after-enter", + "after-leave", + "after-appear", + "enter-cancelled", + "leave-cancelled", + "ppear-cancelled" + ], + "snippet": { + "children": "Transition" + } + }, + "TransitionGroup": { + "name": "TransitionGroup", + "label": "过渡效果组", + "categoryId": "components", + "doc": "https://cn.vuejs.org/api/built-in-components.html#transitiongroup", + "package": "vue", + "props": [ + { + "name": "name", + "label": "名称", + "defaultValue": "", + "title": "用于自动生成过渡 CSS class 名", + "setters": "InputSetter" + }, + { + "name": "tag", + "label": "标签名", + "title": "如果未定义,则渲染为片段 (fragment)", + "setters": "InputSetter" + }, + { + "name": "moveClass", + "label": "moveClass", + "title": "用于自定义过渡期间被应用的 CSS class。", + "setters": "InputSetter" + }, + { + "name": "css", + "label": "应用CSS", + "defaultValue": true, + "title": "是否应用 CSS 过渡 class", + "setters": "BooleanSetter" + }, + { + "name": "type", + "label": "事件类型", + "title": "指定要等待的过渡事件类型来确定过渡结束的时间,默认情况下会自动检测持续时间较长的类型", + "setters": "SelectSetter", + "options": ["transition", "animation"] + }, + { + "name": "duration", + "label": "持续时间", + "title": "显式指定过渡的持续时间", + "setters": ["NumberSetter", "JSONSetter"] + }, + { + "name": "appear", + "label": "使用过渡", + "defaultValue": false, + "title": "是否对初始渲染使用过渡", + "setters": "BooleanSetter" + }, + { + "name": "enterFromClass", + "label": "enterFromClass", + "setters": "InputSetter" + }, + { + "name": "enterActiveClass", + "label": "enterActiveClass", + "setters": "InputSetter" + }, + { + "name": "enterToClass", + "label": "enterToClass", + "setters": "InputSetter" + }, + { + "name": "appearFromClass", + "label": "appearFromClass", + "setters": "InputSetter" + }, + { + "name": "appearActiveClass", + "label": "appearActiveClass", + "setters": "InputSetter" + }, + { + "name": "appearToClass", + "label": "appearToClass", + "setters": "InputSetter" + }, + { + "name": "leaveFromClass", + "label": "leaveFromClass", + "setters": "InputSetter" + }, + { + "name": "leaveActiveClass", + "label": "leaveActiveClass", + "setters": "InputSetter" + }, + { + "name": "leaveToClass", + "label": "leaveToClass", + "setters": "InputSetter" + } + ], + "events": [ + "before-enter", + "before-leave", + "enter", + "leave", + "appear", + "after-enter", + "after-leave", + "after-appear", + "enter-cancelled", + "leave-cancelled", + "ppear-cancelled" + ], + "snippet": { + "children": "TransitionGroup" + } + }, + "KeepAlive": { + "name": "KeepAlive", + "label": "缓存切换组件", + "categoryId": "components", + "doc": "https://cn.vuejs.org/api/built-in-components.html#keepalive", + "package": "vue", + "props": [ + { + "name": "include", + "label": "匹配包含", + "title": "如果指定,则只有与 `include` 名称, 匹配的组件才会被缓存。", + "setters": ["InputSetter", "JSONSetter"] + }, + { + "name": "exclude", + "label": "匹配排除", + "title": "任何名称与 `exclude` 匹配的组件都不会被缓存。", + "setters": ["InputSetter", "JSONSetter"] + }, + { + "name": "max", + "label": "最大缓存数", + "title": "最多可以缓存多少组件实例。", + "setters": ["InputSetter"] + } + ] + }, + "Teleport": { + "name": "Teleport", + "label": "传送组件", + "categoryId": "components", + "doc": "https://cn.vuejs.org/api/built-in-components.html#teleport", + "package": "vue", + "props": [ + { + "name": "to", + "label": "目标容器", + "title": "指定目标容器,可以是选择器或实际元素", + "setters": ["InputSetter"] + }, + { + "name": "disabled", + "label": "禁用", + "title": "当值为 `true` 时,内容将保留在其原始位置, 而不是移动到目标容器中, 可以动态更改", + "setters": ["BooleanSetter"] + } + ] + }, + "Suspense": { + "name": "Suspense", + "label": "异步依赖", + "categoryId": "components", + "doc": "https://cn.vuejs.org/api/built-in-components.html#suspense", + "package": "vue", + "props": [ + { + "name": "timeout", + "label": "timeout", + "setters": ["InputSetter"] + } + ] + }, + "RouterLink": { + "name": "RouterLink", + "label": "路由链接", + "categoryId": "components", + "doc": "https://router.vuejs.org/zh/api/interfaces/RouterLinkProps.html", + "package": "vue-router", + "props": [ + { + "name": "to", + "label": "to", + "setters": ["InputSetter"] + }, + { + "name": "replace", + "label": "replace", + "setters": ["BooleanSetter"] + } + ], + "snippet": { + "children": "RouterLink", + "props": { + "to": "/" + } + } + }, + "XTest": { + "name": "XTest", + "label": "测试组件", + "categoryId": "test", + "props": [ + { + "name": "booleanProp", + "label": "布尔值", + "setters": "BooleanSetter", + "title": "提示说明文本", + "defaultValue": true + }, + { + "name": "stringProp", + "setters": "StringSetter" + }, + { + "name": "numberProp", + "setters": "NumberSetter" + }, + { + "name": "selectProp", + "setters": "SelectSetter", + "defaultValue": "default", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "objectProp", + "setters": "ObjectSetter" + }, + { + "name": "arrayProp", + "setters": "ArraySetter" + }, + { + "name": "iconProp", + "setters": "IconSetter" + }, + { + "name": "colorProp", + "setters": "ColorSetter" + }, + { + "name": "modelValue", + "setters": "StringSetter" + }, + { + "name": "syncProp", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "click", + "params": ["props"] + }, + { + "name": "submit", + "params": ["props"] + }, + { + "name": "change", + "params": ["data"] + }, + { + "name": "update:modelValue", + "params": ["value"] + }, + { + "name": "update:syncProp", + "params": ["value"] + } + ], + "slots": [ + { + "name": "default", + "params": ["props", "data"] + }, + { + "name": "extra", + "params": ["props", "data"] + } + ], + "snippet": { + "props": {} + }, + "package": "@vtj/ui" + }, + "XIcon": { + "name": "XIcon", + "label": "图标", + "categoryId": "base", + "props": [ + { + "name": "icon", + "label": "图标", + "setters": "IconSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": ["SelectSetter", "NumberSetter"], + "options": ["default", "large", "small"] + }, + { + "name": "color", + "label": "颜色", + "setters": "ColorSetter" + }, + { + "name": "background", + "label": "背景色", + "setters": "ColorSetter" + }, + { + "name": "src", + "label": "图片Url", + "setters": "InputSetter" + }, + { + "name": "radius", + "label": "圆角值", + "setters": "NumberSetter" + }, + { + "name": "padding", + "label": "内边距", + "setters": "NumberSetter" + }, + { + "name": "hoverEffect", + "label": "悬停效果", + "setters": "BooleanSetter" + } + ], + "snippet": { + "props": { + "icon": "Star" + } + }, + "package": "@vtj/ui" + }, + "XContainer": { + "name": "XContainer", + "label": "容器", + "categoryId": "base", + "props": [ + { + "name": "tag", + "label": "标签名", + "setters": "StringSetter", + "defaultValue": "div" + }, + { + "name": "fit", + "label": "高度自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "宽度", + "setters": "StringSetter" + }, + { + "name": "height", + "label": "高度", + "setters": "StringSetter" + }, + { + "name": "flex", + "label": "flex布局", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "inline", + "label": "inline-flex", + "setters": "BooleanSetter" + }, + { + "name": "direction", + "label": "排版方向", + "setters": "SelectSetter", + "options": ["row", "row-reverse", "column", "column-reverse"], + "defaultValue": "row" + }, + { + "name": "wrap", + "label": "换行", + "setters": "SelectSetter", + "options": ["nowrap", "wrap", "wrap-reverse"], + "defaultValue": "nowrap" + }, + { + "name": "justify", + "label": "主轴对齐", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "space-between", "space-around"], + "defaultValue": "flex-start" + }, + { + "name": "align", + "label": "交叉轴对齐", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "baseline", "stretch"], + "defaultValue": "flex-start" + }, + { + "name": "alignContent", + "label": "多轴线对齐", + "title": "多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "space-between", "space-around", "stretch"], + "defaultValue": "stretch" + }, + { + "name": "grow", + "label": "自动放大", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "shrink", + "label": "自动缩小", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "alignSelf", + "label": "alignSelf", + "title": "单个项目有与其他项目不一样的对齐方式。可覆盖容器的align-items属性", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "baseline", "stretch"], + "defaultValue": "auto" + }, + { + "name": "overflow", + "label": "overflow", + "setters": "SelectSetter", + "options": ["auto", "hidden", "visible"] + }, + { + "name": "padding", + "label": "内边距", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "gap", + "label": "子组件间隔", + "setters": "BooleanSetter" + }, + { + "name": "autoPointer", + "label": "autoPointer", + "setters": "BooleanSetter" + } + ], + "snippet": { + "props": { + "padding": true + } + }, + "package": "@vtj/ui" + }, + "XAction": { + "name": "XAction", + "label": "操作按钮", + "categoryId": "base", + "props": [ + { + "name": "name", + "label": "名称标识", + "setters": "StringSetter" + }, + { + "name": "label", + "label": "标题文本", + "setters": "StringSetter" + }, + { + "name": "value", + "label": "动作值", + "setters": "StringSetter", + "title": "用来传输数据" + }, + { + "name": "icon", + "label": "图标配置", + "setters": "IconSetter" + }, + { + "name": "mode", + "label": "模式", + "setters": "SelectSetter", + "options": ["button", "text", "icon"], + "defaultValue": "button" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "menus", + "label": "菜单配置", + "setters": "JsonSetter" + }, + { + "name": "tooltip", + "label": "Tooltip配置", + "setters": ["StringSetter", "JsonSetter"] + }, + { + "name": "badge", + "label": "Badge配置", + "setters": ["StringSetter", "NumberSetter", "JsonSetter"] + }, + { + "name": "dropdown", + "label": "Dropdown配置", + "setters": "JsonSetter" + }, + { + "name": "button", + "label": "Button配置", + "setters": "JsonSetter", + "title": "mode为button时有效" + }, + { + "name": "disabled", + "label": "禁用", + "setters": "BooleanSetter" + }, + { + "name": "background", + "label": "背景", + "setters": "SelectSetter", + "options": ["always", "hover", "none"] + }, + { + "name": "circle", + "label": "圆形", + "setters": "BooleanSetter" + } + ], + "events": ["click", "command"], + "slots": [ + { + "name": "item", + "params": ["item", "index"] + }, + { + "name": "default" + } + ], + "snippet": { + "props": { + "label": "操作按钮" + } + }, + "package": "@vtj/ui" + }, + "XActionBar": { + "name": "XActionBar", + "label": "操作按钮集", + "categoryId": "base", + "props": [ + { + "name": "items", + "title": "动作项", + "setters": "ArraySetter" + }, + { + "name": "mode", + "label": "模式", + "setters": "SelectSetter", + "options": ["button", "text", "icon"], + "defaultValue": "button" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "tooltip", + "label": "Tooltip配置", + "setters": ["StringSetter", "JsonSetter"] + }, + { + "name": "badge", + "label": "Badge配置", + "setters": ["StringSetter", "NumberSetter", "JsonSetter"] + }, + { + "name": "dropdown", + "label": "Dropdown配置", + "setters": "JsonSetter" + }, + { + "name": "button", + "label": "Button配置", + "setters": "JsonSetter", + "title": "mode为button时有效" + }, + { + "name": "disabled", + "label": "禁用", + "setters": "BooleanSetter" + }, + { + "name": "background", + "label": "背景", + "setters": "SelectSetter", + "options": ["always", "hover", "none"] + }, + { + "name": "circle", + "label": "圆形", + "setters": "BooleanSetter" + } + ], + "events": ["click", "command"], + "snippet": { + "props": { + "items": [ + { + "label": "操作一", + "value": 1 + }, + { + "label": "操作二", + "value": 2 + }, + { + "label": "操作三", + "value": 3 + } + ] + } + }, + "package": "@vtj/ui" + }, + "XQrCode": { + "name": "XQrCode", + "label": "二维码", + "categoryId": "base", + "props": [ + { + "name": "size", + "title": "二维码尺寸", + "setters": "NumberSetter" + }, + { + "name": "content", + "setters": ["StringSetter", "FunctionSetter"] + }, + { + "name": "expired", + "title": "设置过期时间,单位毫秒", + "setters": "NumberSetter" + }, + { + "name": "tip", + "title": "过期时提示文本", + "setters": "StringSetter" + }, + { + "name": "options", + "title": "qrcode工具配置参数:https://www.npmjs.com/package/qrcode", + "setters": "ObjectSetter" + } + ], + "events": [ + { + "name": "refresh" + }, + { + "name": "draw" + } + ], + "slots": ["tip"], + "snippet": { + "props": { + "content": "二维码内容" + } + }, + "package": "@vtj/ui" + }, + "XPanel": { + "name": "XPanel", + "label": "面板", + "categoryId": "layout", + "props": [ + { + "name": "fit", + "label": "fit", + "title": "宽高自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "label": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "border", + "title": "显示边框", + "setters": "BooleanSetter" + }, + { + "name": "radius", + "title": "圆角", + "setters": "BooleanSetter" + }, + { + "name": "card", + "title": "卡片模式", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": ["SelectSetter"], + "options": ["default", "large", "small"] + }, + { + "name": "shadow", + "title": "阴影设置", + "setters": "SelectSetter", + "options": ["none", "always", "hover"] + }, + { + "name": "header", + "title": "头部设置", + "setters": ["StringSetter", "ObjectSetter"] + }, + { + "name": "body", + "title": "body", + "setters": "ObjectSetter" + }, + { + "name": "footer", + "title": "footer", + "setters": "ObjectSetter" + } + ], + "slots": ["default", "actions", "title", "footer"], + "snippet": { + "props": { + "header": "标题" + }, + "children": "内容文本" + }, + "package": "@vtj/ui" + }, + "XAttachment": { + "name": "XAttachment", + "label": "附件", + "categoryId": "data", + "props": [ + { + "name": "modelValue", + "label": "modelValue", + "title": "列表显示的文件", + "setters": "ArraySetter" + }, + { + "name": "selectValue", + "label": "selectValue", + "title": "选中值,开启 selectable 有效", + "setters": "ArraySetter" + }, + { + "name": "uploader", + "label": "uploader", + "title": "文件上传方法", + "setters": "FunctionsSetter" + }, + { + "name": "multiple", + "label": "multiple", + "title": "支持多文件上传, 同时在selectable时控制多选", + "setters": "BooleanSetter" + }, + { + "name": "limit", + "label": "limit", + "title": "允许上传文件的最大数量", + "setters": "NumberSetter" + }, + { + "name": "accept", + "label": "accept", + "title": " 接受上传的文件类型, 如:image/png, image/jpeg, .pptx", + "setters": "StringSetter" + }, + { + "name": "disabled", + "label": "disabled", + "title": "禁止更改文件,不能上传和删除", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "thumbnail", + "label": "thumbnail", + "title": "缩略图生成方法", + "setters": "FunctionSetter" + }, + { + "name": "addable", + "label": "addable", + "title": "可增加", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "removable", + "label": "removable", + "title": "可删除", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "downloadable", + "label": "downloadable", + "title": "可下载", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "previewable", + "label": "previewable", + "title": "可预览", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "selectable", + "label": "selectable", + "title": "可选择", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "clickable", + "label": "clickable", + "title": "可点击", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "listType", + "label": "listType", + "title": "列表类型", + "setters": "SelectSetter", + "options": ["card", "list"], + "defaultValue": "card" + }, + { + "name": "beforeUpload", + "title": "上传前守卫", + "setters": "FunctionSetter" + }, + { + "name": "limitSize", + "title": "允许上传的文件大写最大值, 支持 K / M", + "setters": "StringSetter", + "defaultValue": "10M" + }, + { + "name": "formatter", + "setters": "FunctionSetter" + }, + { + "name": "valueFormatter", + "setters": "FunctionSetter" + }, + { + "name": "previewer", + "setters": "FunctionSetter" + }, + { + "name": "downloader", + "setters": "FunctionSetter" + }, + { + "name": "autoUpload", + "setters": "BooleanSetter" + } + ], + "events": [ + "click", + "preview", + "remove", + "download", + "select", + "change", + "update:modelValue", + "update:selectValue" + ], + "slots": ["tip"], + "snippet": { + "props": {} + }, + "package": "@vtj/ui" + }, + "XDataItem": { + "name": "XDataItem", + "label": "数据项", + "categoryId": "data", + "props": [ + { + "name": "direction", + "title": "排版方向", + "setters": "SelectSetter", + "options": ["row", "column"], + "defaultValue": "column" + }, + { + "name": "imageSrc", + "title": "图片URL", + "setters": "StringSetter" + }, + { + "name": "imageWidth", + "title": "图片宽度", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "imageHeight", + "title": "图片高度", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "icon", + "title": "图片高度", + "setters": ["IconSetter"] + }, + { + "name": "title", + "setters": ["StringSetter"] + }, + { + "name": "description", + "setters": ["StringSetter"] + }, + { + "name": "actions", + "title": "动作按钮 ActionBarItems", + "setters": ["ArraySetter"] + }, + { + "name": "actionBarProps", + "title": "动作条组件配置 ActionBarProps", + "setters": ["ObjectSetter"] + }, + { + "name": "split", + "setters": ["BooleanSetter"] + }, + { + "name": "active", + "setters": ["BooleanSetter"] + }, + { + "name": "hover", + "setters": ["BooleanSetter"] + }, + { + "name": "padding", + "setters": ["BooleanSetter"] + }, + { + "name": "tag", + "label": "标签名", + "setters": "StringSetter", + "defaultValue": "div" + }, + { + "name": "fit", + "label": "高度自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "宽度", + "setters": "StringSetter" + }, + { + "name": "height", + "label": "高度", + "setters": "StringSetter" + }, + { + "name": "flex", + "label": "flex布局", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "inline", + "label": "inline-flex", + "setters": "BooleanSetter" + }, + { + "name": "wrap", + "label": "换行", + "setters": "SelectSetter", + "options": ["nowrap", "wrap", "wrap-reverse"], + "defaultValue": "nowrap" + }, + { + "name": "justify", + "label": "主轴对齐", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "space-between", "space-around"], + "defaultValue": "flex-start" + }, + { + "name": "align", + "label": "交叉轴对齐", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "baseline", "stretch"], + "defaultValue": "flex-start" + }, + { + "name": "alignContent", + "label": "多轴线对齐", + "title": "多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "space-between", "space-around", "stretch"], + "defaultValue": "stretch" + }, + { + "name": "grow", + "label": "自动放大", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "shrink", + "label": "自动缩小", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "alignSelf", + "label": "alignSelf", + "title": "单个项目有与其他项目不一样的对齐方式。可覆盖容器的align-items属性", + "setters": "SelectSetter", + "options": ["flex-start", "flex-end", "center", "baseline", "stretch"], + "defaultValue": "auto" + }, + { + "name": "overflow", + "label": "overflow", + "setters": "SelectSetter", + "options": ["auto", "hidden", "visible"] + }, + { + "name": "padding", + "label": "内边距", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "gap", + "label": "子组件间隔", + "setters": "BooleanSetter" + }, + { + "name": "autoPointer", + "label": "autoPointer", + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "imageClick" + }, + { + "name": "titleClick" + }, + { + "name": "actionClick", + "params": ["action"] + }, + { + "name": "actionCommand", + "params": ["action", "menu"] + } + ], + "slots": [ + { + "name": "image" + }, + { + "name": "title" + }, + { + "name": "description" + }, + { + "name": "actions" + }, + { + "name": "default" + } + ], + "snippet": { + "props": { + "title": "标题文本", + "description": "描述文本示例内容" + } + }, + "package": "@vtj/ui" + }, + "XDialog": { + "name": "XDialog", + "label": "弹窗", + "categoryId": "layout", + "props": [ + { + "name": "modelValue", + "title": "控制是否显示弹窗", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "title", + "setters": "StringSetter" + }, + { + "name": "subtitle", + "setters": "StringSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "left", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "top", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "modal", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "draggable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "resizable", + "setters": "BooleanSetter" + }, + { + "name": "closable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "maximizable", + "setters": "BooleanSetter" + }, + { + "name": "minimizable", + "setters": "BooleanSetter" + }, + { + "name": "mode", + "setters": "SelectSetter", + "options": ["normal", "maximized", "minimized"], + "defaultValue": "normal" + }, + { + "name": "src", + "title": "加载页码url", + "setters": "StringSetter" + }, + { + "name": "beforeClose", + "title": "关闭弹窗回调函数,return true 阻止关闭", + "setters": "FunctionSetter" + }, + { + "name": "submit", + "setters": ["Boolean", "StringSetter"] + }, + { + "name": "cancel", + "setters": ["Boolean", "StringSetter"] + }, + { + "name": "bodyPadding", + "setters": "BooleanSetter" + }, + { + "name": "primary", + "setters": "BooleanSetter" + }, + { + "name": "fit", + "label": "fit", + "title": "宽高自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "label": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "border", + "title": "显示边框", + "setters": "BooleanSetter" + }, + { + "name": "radius", + "title": "圆角", + "setters": "BooleanSetter" + }, + { + "name": "card", + "title": "卡片模式", + "setters": "BooleanSetter" + }, + { + "name": "shadow", + "title": "阴影设置", + "setters": "SelectSetter", + "options": ["none", "always", "hover"] + }, + { + "name": "header", + "title": "头部设置", + "setters": ["StringSetter", "ObjectSetter"] + }, + { + "name": "body", + "title": "body", + "setters": "ObjectSetter" + }, + { + "name": "footer", + "title": "footer", + "setters": "ObjectSetter" + } + ], + "events": [ + { + "name": "update:modelValue", + "params": ["modelValue"] + }, + { + "name": "open", + "params": ["instance"] + }, + { + "name": "close" + }, + { + "name": "destroy" + }, + { + "name": "maximized" + }, + { + "name": "minimized" + }, + { + "name": "normal" + }, + { + "name": "modeChange", + "params": ["mode"] + }, + { + "name": "dragStart", + "params": ["position"] + }, + { + "name": "dragging", + "params": ["position"] + }, + { + "name": "dragEnd", + "params": ["position"] + }, + { + "name": "resizeStart", + "params": ["dir", "mie"] + }, + { + "name": "resizeEnd", + "params": ["dir", "mie"] + }, + { + "name": "resizing", + "params": ["dir", "mie"] + }, + { + "name": "submit" + }, + { + "name": "cancel" + } + ], + "slots": [ + { + "name": "title" + }, + { + "name": "actions" + }, + { + "name": "default" + }, + { + "name": "footer" + }, + { + "name": "extra" + }, + { + "name": "handle" + } + ], + "snippet": { + "props": { + "title": "弹窗标题" + } + }, + "package": "@vtj/ui" + }, + "XDialogForm": { + "name": "XDialogForm", + "label": "弹窗表单", + "categoryId": "form", + "props": [ + { + "name": "modelValue", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "submit", + "setters": ["StringSetter", "BooleanSetter"], + "defaultValue": "确定" + }, + { + "name": "cancel", + "setters": ["StringSetter", "BooleanSetter"], + "defaultValue": "取消" + }, + { + "name": "model", + "setters": "ObjectSetter" + }, + { + "name": "rules", + "setters": "ObjectSetter" + }, + { + "name": "formProps", + "title": "表单XForm组件参数选项", + "setters": "ObjectSetter" + }, + { + "name": "submitMethod", + "title": "表单提交处理方法, return true 关闭弹窗", + "setters": "FunctionSetter" + }, + { + "name": "title", + "setters": "StringSetter" + }, + { + "name": "subtitle", + "setters": "StringSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "left", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "top", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "modal", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "draggable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "resizable", + "setters": "BooleanSetter" + }, + { + "name": "closable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "maximizable", + "setters": "BooleanSetter" + }, + { + "name": "minimizable", + "setters": "BooleanSetter" + }, + { + "name": "mode", + "setters": "SelectSetter", + "options": ["normal", "maximized", "minimized"], + "defaultValue": "normal" + }, + { + "name": "src", + "title": "加载页码url", + "setters": "StringSetter" + }, + { + "name": "beforeClose", + "title": "关闭弹窗回调函数,return true 阻止关闭", + "setters": "FunctionSetter" + }, + { + "name": "bodyPadding", + "setters": "BooleanSetter" + }, + { + "name": "primary", + "setters": "BooleanSetter" + }, + { + "name": "fit", + "label": "fit", + "title": "宽高自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "label": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "border", + "title": "显示边框", + "setters": "BooleanSetter" + }, + { + "name": "radius", + "title": "圆角", + "setters": "BooleanSetter" + }, + { + "name": "card", + "title": "卡片模式", + "setters": "BooleanSetter" + }, + { + "name": "shadow", + "title": "阴影设置", + "setters": "SelectSetter", + "options": ["none", "always", "hover"] + }, + { + "name": "header", + "title": "头部设置", + "setters": ["StringSetter", "ObjectSetter"] + }, + { + "name": "body", + "title": "body", + "setters": "ObjectSetter" + }, + { + "name": "footer", + "title": "footer", + "setters": "ObjectSetter" + } + ], + "events": [ + { + "name": "update:modelValue", + "params": ["modelValue"] + }, + { + "name": "submit", + "params": ["model"] + }, + { + "name": "close" + } + ], + "slots": ["default", "extra", "handle", "footer"], + "snippet": { + "props": { + "title": "弹窗表单" + } + }, + "package": "@vtj/ui" + }, + "XField": { + "name": "XField", + "label": "字段", + "categoryId": "form", + "props": [ + { + "name": "name", + "title": "字段名称", + "setters": "StringSetter" + }, + { + "name": "label", + "title": "字段标题文本", + "setters": "StringSetter" + }, + { + "name": "editor", + "title": "编辑器组件", + "setters": "SelectSetter", + "options": [ + "none", + "text", + "textarea", + "select", + "checkbox", + "radio", + "number", + "date", + "time", + "datetime", + "switch", + "slider", + "rate", + "cascader", + "picker" + ] + }, + { + "name": "props", + "title": "编辑器组件参数", + "setters": "ObjectSetter" + }, + { + "name": "modelValue", + "setters": "StringSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "tooltipMessage", + "title": "是否在tooltip显示校验信息", + "setters": ["BooleanSetter", "ObjectSetter"] + }, + { + "name": "tooltipPosition", + "setters": ["SelectSetter", "NumberSetter"], + "options": ["inner", "outer"], + "defaultValue": "outer" + }, + { + "name": "placeholder", + "setters": "StringSetter" + }, + { + "name": "disabled", + "setters": "BooleanSetter" + }, + { + "name": "readonly", + "setters": "BooleanSetter" + }, + { + "name": "options", + "setters": ["ArraySetter", "FunctionSetter"] + }, + { + "name": "visible", + "setters": "BooleanSetter" + }, + { + "name": "cascader", + "title": "级联字段,根据字段值变化刷新options", + "setters": ["StringSetter", "ArraySetter"] + }, + { + "name": "error", + "setters": "StringSetter" + }, + { + "name": "tip", + "setters": "StringSetter" + }, + { + "name": "inline", + "title": "表单项内容采用inline布局", + "setters": "BooleanSetter" + }, + { + "name": "hidden", + "title": "隐藏域", + "setters": "BooleanSetter" + }, + { + "name": "defaultValue", + "title": "默认值", + "setters": "StringSetter" + }, + { + "name": "labelPosition", + "defaultValue": "", + "setters": "SelectSetter", + "options": ["left", "right", "top"] + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "required", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "rules", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "error", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "showMessage", + "defaultValue": true, + "title": "是否显示校验错误信息", + "label": "错误信息", + "setters": "BooleanSetter" + }, + { + "name": "inlineMessage", + "defaultValue": false, + "title": "是否在行内显示校验信息", + "label": "校验信息", + "setters": "BooleanSetter" + }, + { + "name": "for", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "validateStatus", + "title": "formitem 校验的状态", + "options": ["", "error", "validating", "success"], + "setters": "SelectSetter" + } + ], + "events": ["update:modelValue", "change", "focus", "blur"], + "slots": [ + { + "name": "label" + }, + { + "name": "error", + "params": ["error"] + }, + { + "name": "editor", + "params": ["editor"] + }, + { + "name": "tip" + }, + { + "name": "default" + } + ], + "snippet": { + "props": { + "label": "字段名称" + } + }, + "package": "@vtj/ui" + }, + "XForm": { + "name": "XForm", + "label": "表单", + "categoryId": "form", + "props": [ + { + "name": "model", + "setters": "ObjectSetter" + }, + { + "name": "inline", + "setters": "BooleanSetter" + }, + { + "name": "inlineColumns", + "title": "inline模式显示列数", + "setters": "NumberSetter" + }, + { + "name": "footer", + "setters": "BooleanSetter" + }, + { + "name": "submitText", + "setters": "StringSetter", + "defaultValue": "提交" + }, + { + "name": "resetText", + "setters": "StringSetter", + "defaultValue": "重置" + }, + { + "name": "submitMethod", + "title": "表单提交处理方法", + "setters": "FunctionSetter" + }, + { + "name": "tooltipMessage", + "title": "是否在tooltip显示校验信息", + "setters": ["BooleanSetter", "ObjectSetter"] + }, + { + "name": "enterSubmit", + "title": "回车键触发提交", + "setters": "BooleanSetter" + }, + { + "name": "rules", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "labelPosition", + "defaultValue": "right", + "options": ["left", "right", "top"], + "setters": "SelectSetter" + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "labelSuffix", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "hideRequiredAsterisk", + "defaultValue": false, + "title": "是否显示必填字段的标签旁边的红色星号", + "setters": "BooleanSetter" + }, + { + "name": "requireAsteriskPosition", + "defaultValue": "left", + "title": "星号的位置", + "options": ["left", "right"], + "setters": "SelectSetter" + }, + { + "name": "showMessage", + "defaultValue": true, + "title": "是否显示校验错误信息", + "setters": "BooleanSetter" + }, + { + "name": "inlineMessage", + "defaultValue": false, + "title": "是否以行内形式展示校验信息", + "setters": "BooleanSetter" + }, + { + "name": "statusIcon", + "defaultValue": false, + "title": "是否在输入框中显示校验结果反馈图标", + "setters": "BooleanSetter" + }, + { + "name": "validateOnRuleChange", + "defaultValue": true, + "title": "是否在 rules 属性改变后立即触发一次验证", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollToError", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollIntoViewOptions", + "defaultValue": "", + "setters": ["ExpressionSetter", "BooleanSetter"] + } + ], + "events": [ + { + "name": "change", + "params": ["model"] + }, + { + "name": "submit", + "params": ["model"] + }, + { + "name": "reset" + } + ], + "slots": ["default", "footer", "action"], + "snippet": { + "props": { + "labelWidth": "100px" + }, + "children": [ + { + "name": "XField", + "props": { + "label": "字段名称" + } + } + ] + }, + "package": "@vtj/ui" + }, + "XGrid": { + "name": "XGrid", + "label": "表格", + "categoryId": "data", + "doc": "https://vxetable.cn/#/grid/api", + "props": [ + { + "name": "columns", + "setters": "ArraySetter" + }, + { + "name": "loader", + "title": "数据加载函数: (state) => {list, total}", + "setters": "FunctionSetter" + }, + { + "name": "rowSortable", + "title": "行拖拽排序", + "setters": "BooleanSetter" + }, + { + "name": "columnSortable", + "title": "列拖拽排序", + "setters": "BooleanSetter" + }, + { + "name": "customable", + "title": "开启用户自定义", + "setters": "BooleanSetter" + }, + { + "name": "resizable", + "setters": "BooleanSetter" + }, + { + "name": "pager", + "title": "开启分页功能", + "setters": "BooleanSetter" + }, + { + "name": "page", + "setters": "NumberSetter" + }, + { + "name": "pageSize", + "setters": "NumberSetter" + }, + { + "name": "pageSizes", + "title": "每页显示个数选择器的选项设置", + "setters": "ArraySetter" + }, + { + "name": "auto", + "title": "初始执行加载函数", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "virtual", + "title": "开启虚拟滚动", + "setters": "BooleanSetter" + }, + { + "name": "editable", + "title": "开启编辑模式", + "setters": "BooleanSetter" + }, + { + "name": "cellRenders", + "title": "单元格渲染器", + "setters": "ObjectSetter" + }, + { + "name": "editRenders", + "title": "单元格渲染器", + "setters": "ObjectSetter" + }, + { + "name": "filterRenders", + "title": "过滤器渲染器", + "setters": "ObjectSetter" + }, + { + "name": "id", + "setters": "StringSetter" + }, + { + "name": "data", + "setters": "ArraySetter" + }, + { + "name": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "minHeight", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "maxHeight", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "autoResize", + "setters": "BooleanSetter" + }, + { + "name": "syncResize", + "setters": ["BooleanSetter", "StringSetter"] + }, + { + "name": "stripe", + "setters": "BooleanSetter" + }, + { + "name": "border", + "setters": "BooleanSetter" + }, + { + "name": "round", + "setters": "BooleanSetter" + }, + { + "name": "size", + "setters": "SelectSetter", + "options": ["small", "mini"] + }, + { + "name": "loading", + "setters": "BooleanSetter" + }, + { + "name": "align", + "setters": "SelectSetter", + "options": ["left", "center", "right"] + }, + { + "name": "HeaderAlign", + "setters": "SelectSetter", + "options": ["left", "center", "right"] + }, + { + "name": "FooterAlign", + "setters": "SelectSetter", + "options": ["left", "center", "right"] + }, + { + "name": "showHeader", + "setters": "BooleanSetter" + }, + { + "name": "showFoter", + "setters": "BooleanSetter" + }, + { + "name": "footerData", + "setters": "ArraySetter" + }, + { + "name": "mergeCells", + "setters": "FunctionSetter" + }, + { + "name": "mergeFooterItems", + "setters": "FunctionSetter" + }, + { + "name": "showOverflow", + "setters": "BooleanSetter" + }, + { + "name": "showHeaderOverflow", + "setters": "BooleanSetter" + }, + { + "name": "showFooterOverflow", + "setters": "BooleanSetter" + }, + { + "name": "keepSource", + "setters": "BooleanSetter" + }, + { + "name": "columnConfig", + "setters": "ObjectSetter" + }, + { + "name": "rowConfig", + "setters": "ObjectSetter" + }, + { + "name": "resizeConfig", + "setters": "ObjectSetter" + }, + { + "name": "resizableConfig", + "setters": "ObjectSetter" + }, + { + "name": "seqConfig", + "setters": "ObjectSetter" + }, + { + "name": "sortConfig", + "setters": "ObjectSetter" + }, + { + "name": "filterConfig", + "setters": "ObjectSetter" + }, + { + "name": "exportConfig", + "setters": "ObjectSetter" + }, + { + "name": "importConfig", + "setters": "ObjectSetter" + }, + { + "name": "printConfig", + "setters": "ObjectSetter" + }, + { + "name": "radioConfig", + "setters": "ObjectSetter" + }, + { + "name": "checkboxConfig", + "setters": "ObjectSetter" + }, + { + "name": "tooltipConfig", + "setters": "ObjectSetter" + }, + { + "name": "expandConfig", + "setters": "ObjectSetter" + }, + { + "name": "treeConfig", + "setters": "ObjectSetter" + }, + { + "name": "menuConfig", + "setters": "ObjectSetter" + }, + { + "name": "mouseConfig", + "setters": "ObjectSetter" + }, + { + "name": "keyboardConfig", + "setters": "ObjectSetter" + }, + { + "name": "editConfig", + "setters": "ObjectSetter" + }, + { + "name": "validConfig", + "setters": "ObjectSetter" + }, + { + "name": "editRules", + "setters": "ObjectSetter" + }, + { + "name": "emptyText", + "setters": "StringSetter" + }, + { + "name": "emptyRender", + "setters": "ObjectSetter" + }, + { + "name": "loadingConfig", + "setters": "ObjectSetter" + }, + { + "name": "customConfig", + "setters": "ObjectSetter" + }, + { + "name": "scrollX", + "setters": "ObjectSetter" + }, + { + "name": "scrollY", + "setters": "ObjectSetter" + }, + { + "name": "params", + "setters": "ObjectSetter" + }, + { + "name": "toolbarConfig", + "setters": "ObjectSetter" + }, + { + "name": "pagerConfig", + "setters": "ObjectSetter" + }, + { + "name": "proxyConfig", + "setters": "ObjectSetter" + }, + { + "name": "zoomConfig", + "setters": "ObjectSetter" + }, + { + "name": "layouts", + "setters": "ArraySetter" + } + ], + "events": [ + "rowSort", + "columnSort", + "editChange", + "keydown", + "current-change", + "radio-change", + "checkbox-change", + "checkbox-all", + "checkbox-range-start", + "checkbox-range-change", + "checkbox-range-end", + "cell-click", + "cell-dblclick", + "cell-menu", + "cell-mouseenter", + "cell-mouseleave", + "cell-delete-value", + "header-cell-click", + "header-cell-dblclick", + "header-cell-menu", + "footer-cell-click", + "footer-cell-dblclick", + "footer-cell-menu", + "clear-merge", + "sort-change", + "clear-sort", + "filter-change", + "filter-visible", + "clear-filter", + "resizable-change", + "toggle-row-expand", + "toggle-tree-expand", + "menu-click", + "cell-selected", + "edit-closed", + "edit-activated", + "edit-disabled", + "valid-error", + "scroll", + "custom", + "page-change", + "proxy-query", + "proxy-delete", + "proxy-save", + "toolbar-button-click", + "toolbar-tool-click", + "zoom" + ], + "slots": ["empty", "form", "top", "bottom", "toolbar__buttons", "pager__left"], + "snippet": { + "props": { + "height": "auto", + "columns": [ + { + "type": "seq", + "title": "#" + }, + { + "field": "title", + "title": "标题" + } + ] + } + }, + "package": "@vtj/ui" + }, + "XHeader": { + "name": "XHeader", + "label": "标题头", + "categoryId": "layout", + "props": [ + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "content", + "setters": "StringSetter" + }, + { + "name": "subtitle", + "setters": "StringSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "border", + "setters": "BooleanSetter" + }, + { + "name": "more", + "setters": "BooleanSetter" + } + ], + "events": ["click", "clickIcon"], + "slots": ["default", "subtitle", "actions"], + "snippet": { + "props": { + "content": "标题内容文本", + "subtitle": "这里是子标题内容示例" + } + }, + "package": "@vtj/ui" + }, + "XList": { + "name": "XList", + "label": "列表", + "categoryId": "data", + "props": [ + { + "name": "data", + "setters": ["ObjectSetter", "FunctionSetter"] + }, + { + "name": "itemHeight", + "title": "设置 itemHeight 即自动开启虚拟滚动", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "pager", + "setters": ["BooleanSetter", "ObjectSetter"] + }, + { + "name": "page", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "pageSize", + "setters": "NumberSetter", + "defaultValue": 10 + }, + { + "name": "dataKey", + "title": "数据主键属性名称", + "setters": "StringSetter" + }, + { + "name": "infiniteScroll", + "setters": ["BooleanSetter", "ObjectSetter"] + } + ], + "events": [ + { + "name": "load", + "params": ["state"] + } + ], + "slots": [ + { + "name": "empty" + }, + { + "name": "default", + "params": ["item", "index"] + }, + { + "name": "loading" + }, + { + "name": "nomore" + } + ], + "snippet": { + "props": { + "data": { + "list": ["列表项内容一", "列表项内容二"], + "total": 2 + } + } + }, + "package": "@vtj/ui" + }, + "XQueryForm": { + "name": "XQueryForm", + "label": "查询表单", + "categoryId": "form", + "props": [ + { + "name": "collapsible", + "setters": "BooleanSetter" + }, + { + "name": "items", + "setters": "ArraySetter" + }, + { + "name": "model", + "setters": "ObjectSetter" + }, + { + "name": "inline", + "setters": "BooleanSetter" + }, + { + "name": "inlineColumns", + "title": "inline模式显示列数", + "setters": "NumberSetter" + }, + { + "name": "footer", + "setters": "BooleanSetter" + }, + { + "name": "submitText", + "setters": "StringSetter", + "defaultValue": "提交" + }, + { + "name": "resetText", + "setters": "StringSetter", + "defaultValue": "重置" + }, + { + "name": "submitMethod", + "title": "表单提交处理方法", + "setters": "FunctionSetter" + }, + { + "name": "tooltipMessage", + "title": "是否在tooltip显示校验信息", + "setters": ["BooleanSetter", "ObjectSetter"] + }, + { + "name": "enterSubmit", + "title": "回车键触发提交", + "setters": "BooleanSetter" + }, + { + "name": "rules", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "labelPosition", + "defaultValue": "right", + "options": ["left", "right", "top"], + "setters": "SelectSetter" + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "labelSuffix", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "hideRequiredAsterisk", + "defaultValue": false, + "title": "是否显示必填字段的标签旁边的红色星号", + "setters": "BooleanSetter" + }, + { + "name": "requireAsteriskPosition", + "defaultValue": "left", + "title": "星号的位置", + "options": ["left", "right"], + "setters": "SelectSetter" + }, + { + "name": "showMessage", + "defaultValue": true, + "title": "是否显示校验错误信息", + "setters": "BooleanSetter" + }, + { + "name": "inlineMessage", + "defaultValue": false, + "title": "是否以行内形式展示校验信息", + "setters": "BooleanSetter" + }, + { + "name": "statusIcon", + "defaultValue": false, + "title": "是否在输入框中显示校验结果反馈图标", + "setters": "BooleanSetter" + }, + { + "name": "validateOnRuleChange", + "defaultValue": true, + "title": "是否在 rules 属性改变后立即触发一次验证", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollToError", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollIntoViewOptions", + "defaultValue": "", + "setters": ["ExpressionSetter", "BooleanSetter"] + } + ], + "events": [ + { + "name": "change", + "params": ["model"] + }, + { + "name": "submit", + "params": ["model"] + }, + { + "name": "reset" + }, + "collapsed" + ], + "slots": [ + { + "name": "default" + } + ], + "snippet": { + "children": [ + { + "name": "XField", + "props": { + "label": "条件名称" + } + } + ] + }, + "package": "@vtj/ui" + }, + "XTabs": { + "name": "XTabs", + "label": "选项卡", + "categoryId": "layout", + "props": [ + { + "name": "items", + "setters": "ArraySetter" + }, + { + "name": "border", + "setters": "BooleanSetter" + }, + { + "name": "fit", + "setters": "BooleanSetter" + }, + { + "name": "align", + "setters": "SelectSetter", + "options": ["left", "center", "right"] + }, + { + "name": "modelValue", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "type", + "setters": [ + { + "name": "SelectSetter", + "props": { + "closable": true + } + } + ], + "defaultValue": "", + "options": ["", "card", "border-card"] + }, + { + "name": "closable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "addable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "editable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "tabPosition", + "defaultValue": "top", + "setters": "SelectSetter", + "options": ["top", "right", "bottom", "left"] + }, + { + "name": "stretch", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "beforeLeave", + "defaultValue": "", + "setters": "FunctionSetter" + } + ], + "events": [ + { + "name": "tab-click" + }, + { + "name": "tab-change" + }, + { + "name": "tab-remove" + }, + { + "name": "tab-add" + }, + { + "name": "edit" + }, + { + "name": "update:modelValue" + }, + "actionClick", + "actionCommand" + ], + "slots": ["label", "default"], + "snippet": { + "props": { + "modelValue": "1", + "items": [ + { + "label": "Tab 1", + "value": "1" + }, + { + "label": "Tab 2", + "value": "2" + }, + { + "label": "Tab 3", + "value": "3" + } + ] + } + }, + "package": "@vtj/ui" + }, + "XPicker": { + "name": "XPicker", + "label": "数据选择器", + "categoryId": "form", + "childIncludes": false, + "props": [ + { + "name": "columns", + "title": "表格列配置", + "setters": "ArraySetter" + }, + { + "name": "fields", + "title": "查询条件表单字段配置", + "setters": "ArraySetter" + }, + { + "name": "loader", + "title": "表格数据加载函数", + "setters": "FunctionSetter" + }, + { + "name": "modelValue", + "setters": "StringSetter" + }, + { + "name": "multiple", + "title": "多选模式", + "setters": "BooleanSetter" + }, + { + "name": "raw", + "title": "值为对象模式", + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "setters": "BooleanSetter" + }, + { + "name": "append", + "title": "多选可追加", + "setters": "BooleanSetter" + }, + { + "name": "valueKey", + "title": "值映射字段名称", + "setters": "StringSetter", + "defaultValue": "value" + }, + { + "name": "labelKey", + "title": "输入框显示映射字段名称", + "setters": "StringSetter", + "defaultValue": "label" + }, + { + "name": "queryKey", + "title": "查询参数名称", + "setters": "StringSetter" + }, + { + "name": "preload", + "title": "单选模式,回车时自动检测取回有且计有唯一数据", + "setters": "BooleanSetter" + }, + { + "name": "defaultQuery", + "title": "初始默认查询参数 () => Record", + "setters": "FunctionSetter" + }, + { + "name": "dialogProps", + "title": "弹窗组件配置参数", + "setters": "ObjectSetter" + }, + { + "name": "gridProps", + "title": "表格组件配置参数", + "setters": "ObjectSetter" + }, + { + "name": "formProps", + "title": "查询表单配置参数", + "setters": "ObjectSetter" + }, + { + "name": "formatter", + "title": "接受数据转换函数", + "setters": "FunctionSetter" + }, + { + "name": "valueFormatter", + "title": "发送数据转换函数", + "setters": "FunctionSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTags", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTagsTooltip", + "title": "当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。 要使用此属性,collapse-tags属性必须设定为 true", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "multipleLimit", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "placeholder", + "defaultValue": "Select", + "setters": "InputSetter" + }, + { + "name": "filterable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowCreate", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remote", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "remoteMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remoteShowSuffix", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loadingText", + "defaultValue": "Loading", + "setters": "InputSetter" + }, + { + "name": "noMatchText", + "defaultValue": "No matching data", + "setters": "InputSetter" + }, + { + "name": "noDataText", + "defaultValue": "No data", + "setters": "InputSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "reserveKeyword", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "defaultFirstOption", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "appendTo", + "title": "下拉框挂载到哪个 DOM 元素", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "persistent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "automaticDropdown", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "setters": "InputSetter" + }, + { + "name": "fitInputWidth", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "suffixIcon", + "defaultValue": "ArrowUp", + "setters": "InputSetter" + }, + { + "name": "tagType", + "defaultValue": "info", + "options": ["success", "info", "warning", "danger"], + "setters": "SelectSetter" + }, + { + "name": "tagEffect", + "defaultValue": "light", + "options": ["", "light", "dark", "plain"], + "setters": "SelectSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "defaultValue": 12, + "setters": "NumberSetter" + }, + { + "name": "showArrow", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "label": "placement", + "title": "下拉框出现的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom-start" + }, + { + "name": "fallbackPlacements", + "label": "fallbackPlacements", + "title": "dropdown 可用的 positions", + "setters": "ArraySetter", + "defaultValue": ["bottom-start", "top-start", "right", "left"] + }, + { + "name": "maxCollapseTags", + "label": "maxCollapseTags", + "title": "需要显示的 Tag 的最大数量 只有当 collapse-tags 设置为 true 时才会生效。", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "popperOptions", + "label": "popperOptions", + "title": "popper.js 参数", + "setters": "ObjectSetter", + "defaultValue": {} + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "等价于原生 input aria-label 属性", + "setters": "StringSetter" + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值 ", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "suffixTransition", + "title": "下拉菜单显示/消失时后缀图标的动画", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "title": "input 的 tabindex", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "events": [ + "picked", + "change", + "visible-change", + "remove-tag", + "clear", + "blur", + "focus", + "update:modelValue" + ], + "slots": [], + "snippet": { + "props": {} + }, + "package": "@vtj/ui" + }, + "XImportButton": { + "name": "XImportButton", + "label": "导入按钮", + "categoryId": "base", + "props": [ + { + "name": "uploader", + "title": "文件上传函数", + "setters": "FunctionSetter" + }, + { + "name": "multiple", + "setters": "BooleanSetter" + }, + { + "name": "accept", + "title": "接受上传的文件类型", + "setters": "StringSetter" + }, + { + "name": "parser", + "setters": ["SelectSetter", "FunctionSetter"], + "options": ["text", "json", "base64"] + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "plain", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "text", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "bg", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "link", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "round", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "circle", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loadingIcon", + "setters": "IconSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "nativeType", + "defaultValue": "button", + "setters": "SelectSetter", + "options": ["button ", "submit", "reset"] + }, + { + "name": "autoInsertSpace", + "setters": "BooleanSetter" + }, + { + "name": "color", + "setters": "StringSetter" + }, + { + "name": "dark", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "tag", + "setters": "StringSetter", + "defaultValue": "button" + } + ], + "events": ["success", "fail"], + "slots": ["default"], + "snippet": { + "props": {} + }, + "package": "@vtj/ui" + }, + "XDialogGrid": { + "name": "XDialogGrid", + "label": "弹窗表格", + "categoryId": "form", + "props": [ + { + "name": "modelValue", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "columns", + "title": "表格列配置", + "setters": "ArraySetter" + }, + { + "name": "model", + "setters": "ObjectSetter" + }, + { + "name": "rules", + "setters": "ObjectSetter" + }, + { + "name": "formatter", + "title": " model数据转换为表格数据", + "setters": "FunctionSetter" + }, + { + "name": "valueFormatter", + "title": " 表格数据转换为model数据", + "setters": "FunctionSetter" + }, + { + "name": "puls", + "title": "显示增行按钮", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "minus", + "title": "显示删行按钮", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "submitMethod", + "title": "表单提交处理方法, return true 关闭弹窗", + "setters": "FunctionSetter" + }, + { + "name": "gridProps", + "title": "表格其他配置", + "setters": "ObjectSetter" + }, + { + "name": "title", + "setters": "StringSetter" + }, + { + "name": "subtitle", + "setters": "StringSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "left", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "top", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "modal", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "draggable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "resizable", + "setters": "BooleanSetter" + }, + { + "name": "closable", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "maximizable", + "setters": "BooleanSetter" + }, + { + "name": "minimizable", + "setters": "BooleanSetter" + }, + { + "name": "mode", + "setters": "SelectSetter", + "options": ["normal", "maximized", "minimized"], + "defaultValue": "normal" + }, + { + "name": "src", + "title": "加载页码url", + "setters": "StringSetter" + }, + { + "name": "beforeClose", + "title": "关闭弹窗回调函数,return true 阻止关闭", + "setters": "FunctionSetter" + }, + { + "name": "bodyPadding", + "setters": "BooleanSetter" + }, + { + "name": "primary", + "setters": "BooleanSetter" + }, + { + "name": "fit", + "label": "fit", + "title": "宽高自适应", + "setters": "BooleanSetter" + }, + { + "name": "width", + "label": "width", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "height", + "label": "height", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "border", + "title": "显示边框", + "setters": "BooleanSetter" + }, + { + "name": "radius", + "title": "圆角", + "setters": "BooleanSetter" + }, + { + "name": "card", + "title": "卡片模式", + "setters": "BooleanSetter" + }, + { + "name": "shadow", + "title": "阴影设置", + "setters": "SelectSetter", + "options": ["none", "always", "hover"] + }, + { + "name": "header", + "title": "头部设置", + "setters": ["StringSetter", "ObjectSetter"] + }, + { + "name": "body", + "title": "body", + "setters": "ObjectSetter" + }, + { + "name": "footer", + "title": "footer", + "setters": "ObjectSetter" + } + ], + "events": [ + { + "name": "update:modelValue", + "params": ["modelValue"] + }, + { + "name": "submit", + "params": ["model"] + }, + { + "name": "close" + } + ], + "slots": ["buttons", "extra", "top"], + "snippet": { + "props": { + "title": "弹窗表格" + } + }, + "package": "@vtj/ui" + }, + "XCaptcha": { + "name": "XCaptcha", + "label": "图形验证码", + "categoryId": "form", + "props": [ + { + "name": "src", + "setters": "FunctionSetter", + "title": "() => MaybePromise" + }, + { + "name": "maxlength", + "title": "验证码长度", + "setters": "NumberSetter", + "defaultValue": 4 + }, + { + "name": "placeholder", + "setters": "StringSetter", + "defaultValue": "请输入图形验证码" + }, + { + "name": "validate", + "setters": "FunctionSetter", + "title": "校验函数:(value: string) => MaybePromise" + }, + { + "name": "type", + "defaultValue": "text", + "options": ["text", "textarea"], + "setters": ["SelectSetter", "InputSetter"] + }, + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "minlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "showWordLimit", + "defaultValue": false, + "title": "是否显示输入字数统计,只在 type = \"text\" 或 type = \"textarea\" 时有效", + "label": "字数统计", + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "formatter", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "parser", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "showPassword", + "defaultValue": false, + "title": "是否显示切换密码图标", + "label": "密码图标", + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "prefix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "suffix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rows", + "defaultValue": 2, + "setters": "NumberSetter" + }, + { + "name": "autosize", + "defaultValue": false, + "setters": ["BooleanSetter", "JSONStter"] + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "max", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "min", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "step", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "resize", + "defaultValue": "", + "options": ["none", "both", "horizontal", "vertical"], + "setters": "InputSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "form", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "aria-label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "label": "表单校验", + "setters": "BooleanSetter" + }, + { + "name": "inputStyle", + "defaultValue": {}, + "setters": ["JSONSetter"] + } + ], + "events": [ + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "change" + }, + { + "name": "input" + }, + { + "name": "clear" + }, + { + "name": "update:modelValue" + } + ], + "snippet": { + "props": { + "src": { + "type": "JSFunction", + "value": "() => 'https://dummyimage.com/300x120'" + } + } + }, + "package": "@vtj/ui" + }, + "XVerify": { + "name": "XVerify", + "label": "短信验证码", + "categoryId": "form", + "props": [ + { + "name": "api", + "setters": "FunctionSetter", + "title": "() => Promise" + }, + { + "name": "maxlength", + "title": "验证码长度", + "setters": "NumberSetter", + "defaultValue": 6 + }, + { + "name": "placeholder", + "setters": "StringSetter", + "defaultValue": "请输入图形验证码" + }, + { + "name": "seconds", + "setters": "NumberSetter", + "title": "可重发秒数", + "defaultValue": 60 + }, + { + "name": "type", + "defaultValue": "text", + "options": ["text", "textarea"], + "setters": ["SelectSetter", "InputSetter"] + }, + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "minlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "showWordLimit", + "defaultValue": false, + "title": "是否显示输入字数统计,只在 type = \"text\" 或 type = \"textarea\" 时有效", + "label": "字数统计", + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "formatter", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "parser", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "showPassword", + "defaultValue": false, + "title": "是否显示切换密码图标", + "label": "密码图标", + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "prefix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "suffix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rows", + "defaultValue": 2, + "setters": "NumberSetter" + }, + { + "name": "autosize", + "defaultValue": false, + "setters": ["BooleanSetter", "JSONStter"] + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "max", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "min", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "step", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "resize", + "defaultValue": "", + "options": ["none", "both", "horizontal", "vertical"], + "setters": "InputSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "form", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "aria-label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "label": "表单校验", + "setters": "BooleanSetter" + }, + { + "name": "inputStyle", + "defaultValue": {}, + "setters": ["JSONSetter"] + } + ], + "events": [ + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "change" + }, + { + "name": "input" + }, + { + "name": "clear" + }, + { + "name": "update:modelValue" + } + ], + "snippet": { + "props": { + "src": { + "type": "JSFunction", + "value": "async () => true" + } + } + }, + "package": "@vtj/ui" + }, + "ElAffix": { + "name": "ElAffix", + "label": "固钉", + "categoryId": "nav", + "doc": "https://element-plus.org/zh-CN/component/affix.html", + "package": "element-plus", + "props": [ + { + "name": "offset", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "position", + "defaultValue": "top", + "setters": "SelectSetter", + "options": ["top", "bottom"] + }, + { + "name": "target", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "z-index", + "defaultValue": 100, + "setters": "NumberSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "scroll" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElAffix", + "children": [ + { + "name": "ElButton", + "props": { + "type": "primary" + }, + "children": "Affix 固钉" + } + ] + } + }, + "ElAlert": { + "name": "ElAlert", + "childIncludes": true, + "label": "提示", + "doc": "https://element-plus.org/zh-CN/component/alert.html", + "categoryId": "other", + "package": "element-plus", + "props": [ + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "type", + "defaultValue": "info", + "setters": "SelectSetter", + "options": ["success", "warning", "info", "error"] + }, + { + "name": "description", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "closable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "center", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "closeText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "showIcon", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "setters": "SelectSetter", + "options": ["light", "dark"] + } + ], + "events": [ + { + "name": "close" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "title" + } + ], + "snippet": { + "props": { + "title": "success alert", + "type": "success" + } + } + }, + "ElAnchor": { + "name": "ElAnchor", + "label": "锚点", + "doc": "https://element-plus.org/zh-CN/component/anchor.html", + "categoryId": "other", + "package": "element-plus", + "props": [ + { + "name": "container", + "label": "container", + "title": "滚动的容器", + "setters": "StringSetter" + }, + { + "name": "offset", + "label": "offset", + "title": "设置锚点滚动的偏移量", + "setters": "NumberSetter", + "defaultValue": 0 + }, + { + "name": "bound", + "label": "bound", + "title": "触发锚点的元素的位置偏移量", + "setters": "NumberSetter", + "defaultValue": 15 + }, + { + "name": "duration", + "label": "duration", + "title": "设置容器滚动持续时间,单位为毫秒", + "setters": "NumberSetter", + "defaultValue": 300 + }, + { + "name": "marker", + "label": "marker", + "title": "是否显示标记", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "type", + "label": "type", + "title": "设置锚点类型", + "setters": "SelectSetter", + "options": ["default", "underline"], + "defaultValue": "default" + }, + { + "name": "direction", + "label": "direction", + "title": "设置锚点方向", + "setters": "SelectSetter", + "options": ["vertical", "horizontal"], + "defaultValue": "horizontal" + }, + { + "name": "selectScrollTop", + "title": "滚动时,链接是否选中位于顶部", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": ["change", "click"], + "slots": ["default"], + "snippet": { + "props": { + "offset": "70" + }, + "children": [ + { + "name": "ElAnchorLink", + "props": { + "href": "" + }, + "children": "基本用法" + } + ] + } + }, + "ElAnchorLink": { + "name": "ElAnchorLink", + "label": "锚点链接", + "doc": "https://element-plus.org/zh-CN/component/anchor.html", + "categoryId": "other", + "package": "element-plus", + "props": [ + { + "name": "title", + "label": "title", + "title": "链接的文本内容", + "setters": "StringSetter" + }, + { + "name": "href", + "label": "href", + "title": "链接的地址", + "setters": "StringSetter" + } + ], + "slots": ["default", "sub-link"], + "snippet": { + "props": { + "href": "" + }, + "children": "基本用法" + } + }, + "ElAutocomplete": { + "name": "ElAutocomplete", + "label": "自动补全输入框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/autocomplete.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "title": "选中项绑定值", + "setters": "StringSetter" + }, + { + "name": "placeholder", + "title": "占位文本", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "clearable", + "title": "是否可清空", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "title": "自动补全组件是否被禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "valueKey", + "title": "输入建议对象中用于显示的键名", + "defaultValue": "value", + "setters": "StringSetter" + }, + { + "name": "debounce", + "defaultValue": 300, + "title": "获取输入建议的防抖延时", + "setters": "NumberSetter" + }, + { + "name": "placement", + "defaultValue": "bottom-start", + "title": "菜单弹出位置", + "options": [ + "top ", + "top-start", + "top-end", + "top-end", + "bottom", + "bottom-start", + "bottom-end" + ], + "setters": "SelectSetter" + }, + { + "name": "fetchSuggestions", + "defaultValue": "", + "title": "获取输入建议的方法", + "setters": ["ArraySetter", "FunctionSetter"] + }, + { + "name": "triggerOnFocus", + "defaultValue": true, + "title": "是否在输入框focus时显示建议列表", + "setters": "BooleanSetter" + }, + { + "name": "selectWhenUnmatched", + "defaultValue": false, + "title": "在输入没有任何匹配建议的情况下,按下回车是否触发select事件", + "setters": "BooleanSetter" + }, + { + "name": "name", + "title": "等价于原生 input name 属性", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "aria-label", + "defaultValue": "", + "title": "原生 aria-label属性", + "setters": "StringSetter" + }, + { + "name": "hideLoading", + "title": "是否隐藏远程加载时的加载图标", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "title": "下拉列表的类名", + "setters": "StringSetter" + }, + { + "name": "teleported", + "title": "是否将下拉列表元素插入 append-to 指向的元素下", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "highlightFirstItem", + "defaultValue": false, + "title": "是否默认突出显示远程搜索建议中的第一项", + "setters": "BooleanSetter" + }, + { + "name": "fit-input-width", + "defaultValue": false, + "title": "下拉框是否与输入框同宽", + "setters": "BooleanSetter" + }, + { + "name": "popperAppendToBody", + "defaultValue": false, + "title": "是否将下拉列表插入至body元素", + "setters": "BooleanSetter" + } + ], + "slots": [ + { + "name": "default", + "params": ["item"] + }, + { + "name": "prefix" + }, + { + "name": "suffix" + }, + { + "name": "prepend" + }, + { + "name": "append" + }, + { + "name": "loading" + } + ], + "events": [ + { + "name": "update:modelValue" + }, + { + "name": "select" + }, + { + "name": "change" + } + ], + "snippet": { + "props": { + "fetchSuggestions": { + "type": "JSFunction", + "value": "(function (queryString, cb) {\r\n\r\n const list = [\r\n { value: 'vue', link: 'https://github.com/vuejs/vue' },\r\n { value: 'element', link: 'https://github.com/ElemeFE/element' },\r\n { value: 'cooking', link: 'https://github.com/ElemeFE/cooking' },\r\n { value: 'mint-ui', link: 'https://github.com/ElemeFE/mint-ui' },\r\n { value: 'vuex', link: 'https://github.com/vuejs/vuex' },\r\n { value: 'vue-router', link: 'https://github.com/vuejs/vue-router' },\r\n { value: 'babel', link: 'https://github.com/babel/babel' }\r\n ];\r\n\r\n const results = list.filter(n => n.value.startsWith(queryString));\r\n\r\n cb(results);\r\n\r\n})" + } + } + } + }, + "ElAvatar": { + "name": "ElAvatar", + "label": "头像", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/avatar.html", + "package": "element-plus", + "props": [ + { + "name": "icon", + "defaultValue": "", + "setters": "IconSetter" + }, + { + "name": "size", + "setters": ["SelectSetter", "NumberSetter"], + "options": ["large", "default", "small"], + "defaultValue": "default" + }, + { + "name": "shape", + "defaultValue": "circle", + "options": ["circle", "square"], + "setters": "SelectSetter" + }, + { + "name": "src", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "srcSet", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "alt", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "fit", + "defaultValue": "cover", + "options": ["fill", "contain", "cover", "none", "scale-down"], + "setters": "SelectSetter" + } + ], + "events": ["error"], + "slots": ["default", "icon"], + "snippet": { + "props": { + "src": "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" + } + } + }, + "ElBacktop": { + "name": "ElBacktop", + "label": "回到顶部", + "categoryId": "nav", + "doc": "https://element-plus.org/zh-CN/component/backtop.html", + "package": "element-plus", + "props": [ + { + "name": "target", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "visibilityHeight", + "defaultValue": 200, + "setters": "NumberSetter" + }, + { + "name": "right", + "defaultValue": 40, + "setters": "NumberSetter" + }, + { + "name": "bottom", + "defaultValue": 40, + "setters": "NumberSetter" + } + ], + "events": [ + { + "name": "click" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElBacktop", + "children": [ + { + "name": "component", + "props": { + "is": "div", + "style": { + "height": "100%", + "textAlign": "center", + "width": "100px", + "lineHeight": "40px", + "color": "#1989fa" + } + }, + "children": "UP" + } + ] + } + }, + "ElBadge": { + "name": "ElBadge", + "label": "徽章", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/badge.html", + "package": "element-plus", + "props": [ + { + "name": "value", + "defaultValue": "", + "title": "显示值", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "max", + "defaultValue": 99, + "setters": "NumberSetter" + }, + { + "name": "isDot", + "defaultValue": false, + "title": "是否显示小圆点。", + "setters": "BooleanSetter" + }, + { + "name": "hidden", + "defaultValue": false, + "title": "是否隐藏 Badge。", + "setters": "BooleanSetter" + }, + { + "name": "type", + "defaultValue": "danger", + "title": "badge 类型。", + "options": ["primary", "success", "warning", "danger", "info"], + "setters": "SelectSetter" + }, + { + "name": "showZero", + "title": "值为零时是否显示 Badge ", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "color", + "title": "背景色", + "setters": "ColorSetter" + }, + { + "name": "offset", + "title": "badge 的偏移量", + "setters": "ArraySetter" + }, + { + "name": "badgeStyle", + "title": "自定义 badge 样式", + "setters": "ObjectSetter" + }, + { + "name": "badgeClass", + "title": "自定义 badge 类名", + "setters": "StringSetter" + } + ], + "slots": ["default", "content"], + "snippet": { + "props": { + "value": 12 + }, + "children": [ + { + "name": "ElButton", + "children": "评论" + } + ] + } + }, + "ElBreadcrumb": { + "name": "ElBreadcrumb", + "childIncludes": ["ElBreadcrumbItem"], + "label": "面包屑", + "categoryId": "nav", + "doc": "https://element-plus.org/zh-CN/component/breadcrumb.html", + "package": "element-plus", + "props": [ + { + "name": "separator", + "defaultValue": "/", + "setters": "InputSetter" + }, + { + "name": "separatorIcon", + "defaultValue": "", + "setters": ["InputSetter"] + } + ], + "slots": ["default", "separatorIcon"], + "snippet": { + "children": [ + { + "name": "ElBreadcrumbItem", + "children": "主页" + }, + { + "name": "ElBreadcrumbItem", + "children": "列表" + }, + { + "name": "ElBreadcrumbItem", + "children": "详情" + } + ] + } + }, + "ElBreadcrumbItem": { + "name": "ElBreadcrumbItem", + "label": "面包屑项", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "to", + "defaultValue": "", + "setters": ["InputSetter", "JSONSetter"] + }, + { + "name": "replace", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElBreadcrumbItem", + "children": "BreadcrumbItem" + } + }, + "ElButton": { + "name": "ElButton", + "label": "按钮", + "categoryId": "base", + "doc": "https://element-plus.org/zh-CN/component/button.html", + "props": [ + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "plain", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "text", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "bg", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "link", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "round", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "circle", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loadingIcon", + "setters": "IconSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "icon", + "setters": "IconSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "nativeType", + "defaultValue": "button", + "setters": "SelectSetter", + "options": ["button ", "submit", "reset"] + }, + { + "name": "autoInsertSpace", + "setters": "BooleanSetter" + }, + { + "name": "color", + "setters": "StringSetter" + }, + { + "name": "dark", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "tag", + "setters": "StringSetter", + "defaultValue": "button" + } + ], + "events": ["click"], + "slots": ["default", "loading", "icon", "tag"], + "snippet": { + "name": "ElButton", + "children": "按钮", + "props": { + "type": "primary" + } + }, + "package": "element-plus" + }, + "ElButtonGroup": { + "name": "ElButtonGroup", + "childIncludes": ["ElButton"], + "label": "按钮组", + "categoryId": "base", + "props": [ + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + } + ], + "slots": ["default"], + "snippet": { + "name": "ElButtonGroup", + "children": [ + { + "name": "ElButton", + "children": "Button1" + }, + { + "name": "ElButton", + "children": "Button2" + }, + { + "name": "ElButton", + "children": "Button3" + } + ] + }, + "package": "element-plus" + }, + "ElCalendar": { + "name": "ElCalendar", + "label": "日历", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/calendar.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["StringSetter", "ExpressionSetter"] + }, + { + "name": "range", + "defaultValue": "", + "setters": ["ArraySetter", "JSONSetter"] + } + ], + "events": ["update:modelValue"], + "slots": [ + { + "name": "date-cell" + }, + { + "name": "header" + } + ] + }, + "ElCard": { + "name": "ElCard", + "label": "卡片", + "categoryId": "data", + "package": "element-plus", + "doc": "https://element-plus.org/zh-CN/component/card.html", + "props": [ + { + "name": "header", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "footer", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "bodyStyle", + "setters": "JSONSetter" + }, + { + "name": "bodyClass", + "setters": "StringSetter" + }, + { + "name": "shadow", + "defaultValue": "always", + "options": ["always", "hover", "never"], + "setters": "SelectSetter" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "header" + }, + { + "name": "footer" + } + ], + "snippet": { + "props": { + "header": "标题" + }, + "children": "内容文本" + } + }, + "ElCarousel": { + "name": "ElCarousel", + "label": "走马灯", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/carousel.html", + "childIncludes": ["ElCarouselItem"], + "package": "element-plus", + "props": [ + { + "name": "height", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "initialIndex", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "trigger", + "defaultValue": "hover", + "options": ["hover", "click"], + "setters": "SelectSetter" + }, + { + "name": "autoplay", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "interval", + "defaultValue": 3000, + "setters": "NumberSetter" + }, + { + "name": "indicatorPosition", + "defaultValue": "", + "options": ["", "outside", "none"], + "label": "指示器", + "setters": "InputSetter" + }, + { + "name": "arrow", + "defaultValue": "hover", + "options": ["always", "hover", "never"], + "setters": "SelectSetter" + }, + { + "name": "type", + "defaultValue": "", + "options": ["", "card"], + "setters": "SelectSetter" + }, + { + "name": "cardScale", + "defaultValue": 0.83, + "setters": "NumberSetter" + }, + { + "name": "loop", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "direction", + "defaultValue": "horizontal", + "options": ["horizontal", "vertical"], + "setters": "SelectSetter" + }, + { + "name": "pauseOnHover", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "motionBlur", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": ["change"], + "slots": ["default"], + "snippet": { + "props": { + "height": "300px", + "style": { + "width": "100%" + } + }, + "children": [ + { + "name": "ElCarouselItem", + "props": { + "style": { + "width": "100%" + } + }, + "children": [ + { + "name": "component", + "props": { + "is": "img", + "style": { + "width": "100%", + "height": "300px" + }, + "src": "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" + } + } + ], + "directives": [ + { + "name": "vFor", + "value": { + "type": "JSExpression", + "value": "3" + } + } + ] + } + ] + } + }, + "ElCarouselItem": { + "name": "ElCarouselItem", + "label": "走马灯子项", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "style": { + "width": "100%" + } + }, + "children": [ + { + "name": "component", + "props": { + "is": "img", + "style": { + "width": "100%", + "height": "300px" + }, + "src": "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" + } + } + ] + } + }, + "ElCascader": { + "name": "ElCascader", + "label": "级联选择器", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/cascader.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中项绑定值", + "setters": ["StringSetter", "NumberSetter", "ObjectSetter"] + }, + { + "name": "options", + "title": "选项的数据源, value 和 label 可以通过 CascaderProps 自定义", + "defaultValue": [], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "props", + "title": "配置选项", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "size", + "defaultValue": "", + "title": "尺寸", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "placeholder", + "title": "输入框占位文本", + "setters": "StringSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "title": "是否支持清空选项", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "showAllLevels", + "defaultValue": true, + "title": "输入框中是否显示选中值的完整路径", + "setters": "BooleanSetter" + }, + { + "name": "collapseTags", + "title": "多选模式下是否折叠Tag", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTagsTooltip", + "defaultValue": false, + "title": "当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。 要使用此属性,collapseTags属性必须设定为 true", + "setters": "BooleanSetter" + }, + { + "name": "separator", + "title": "用于分隔选项的字符", + "defaultValue": "/", + "setters": "StringSetter" + }, + { + "name": "filterable", + "title": "该选项是否可以被搜索", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterMethod", + "title": "自定义搜索逻辑,第一个参数是node,第二个参数是keyword,返回的布尔值表示是否保留该选项", + "defaultValue": "", + "setters": ["FunctionSetter", "ExpressionSetter"] + }, + { + "name": "debounce", + "title": "搜索关键词正在输入时的去抖延迟,单位为毫秒", + "defaultValue": 300, + "setters": "NumberSetter" + }, + { + "name": "beforeFilter", + "title": "过滤函数调用前,所要调用的钩子函数,该函数接收要过滤的值作为参数。 如果该函数的返回值是 false 或者是一个被拒绝的 Promise,那么接下来的过滤逻辑便不会执行", + "defaultValue": "", + "setters": ["FunctionSetter", "ExpressionSetter"] + }, + { + "name": "popperClass", + "title": "弹出内容的自定义类名", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "teleported", + "title": "弹层是否使用 teleport", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tagType", + "title": "标签类型", + "defaultValue": "info", + "options": ["success", "info", "warning", "danger"], + "setters": "SelectSetter" + }, + { + "name": "tag-effect", + "title": "tag effect", + "defaultValue": "light", + "options": ["light", "dark", "plain"], + "setters": "SelectSetter" + }, + { + "name": "validateEvent", + "title": "输入时是否触发表单的校验", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "maxCollapseTags", + "title": "需要显示的 Tag 的最大数量 只有当 collapse-tags 设置为 true 时才会生效。", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "empty-values", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "value-on-clear", + "title": "清空选项的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "ArraySetter"] + }, + { + "name": "persistent", + "title": "当下拉框未被激活并且persistent设置为false,下拉框容器会被删除。", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "fallback-placements", + "title": "Tooltip 可用的 positions", + "setters": "ArraySetter" + }, + { + "name": "placement", + "title": "下拉框出现的位置", + "defaultValue": "bottom-start", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "setters": "SelectSetter" + }, + { + "name": "popperAppendToBody", + "defaultValue": true, + "title": "是否将弹出的内容直接插入到 body 元素。 在弹出内容的边框定位出现问题时,可将该属性设置为 false", + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "expand-change" + }, + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "clear" + }, + { + "name": "visible-change" + }, + { + "name": "remove-tag" + }, + { + "name": "update:modelValue" + } + ], + "slots": [ + { + "name": "default", + "params": ["node", "data"] + }, + { + "name": "empty" + } + ], + "snippet": { + "props": { + "options": [ + { + "value": "guide", + "label": "Guide", + "children": [ + { + "value": "disciplines", + "label": "Disciplines", + "children": [ + { + "value": "consistency", + "label": "Consistency" + }, + { + "value": "feedback", + "label": "Feedback" + }, + { + "value": "efficiency", + "label": "Efficiency" + }, + { + "value": "controllability", + "label": "Controllability" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "side nav", + "label": "Side Navigation" + }, + { + "value": "top nav", + "label": "Top Navigation" + } + ] + } + ] + }, + { + "value": "component", + "label": "Component", + "children": [ + { + "value": "basic", + "label": "Basic", + "children": [ + { + "value": "layout", + "label": "Layout" + }, + { + "value": "color", + "label": "Color" + }, + { + "value": "typography", + "label": "Typography" + }, + { + "value": "icon", + "label": "Icon" + }, + { + "value": "button", + "label": "Button" + } + ] + }, + { + "value": "form", + "label": "Form", + "children": [ + { + "value": "radio", + "label": "Radio" + }, + { + "value": "checkbox", + "label": "Checkbox" + }, + { + "value": "input", + "label": "Input" + }, + { + "value": "input-number", + "label": "InputNumber" + }, + { + "value": "select", + "label": "Select" + }, + { + "value": "cascader", + "label": "Cascader" + }, + { + "value": "switch", + "label": "Switch" + }, + { + "value": "slider", + "label": "Slider" + }, + { + "value": "time-picker", + "label": "TimePicker" + }, + { + "value": "date-picker", + "label": "DatePicker" + }, + { + "value": "datetime-picker", + "label": "DateTimePicker" + }, + { + "value": "upload", + "label": "Upload" + }, + { + "value": "rate", + "label": "Rate" + }, + { + "value": "form", + "label": "Form" + } + ] + }, + { + "value": "data", + "label": "Data", + "children": [ + { + "value": "table", + "label": "Table" + }, + { + "value": "tag", + "label": "Tag" + }, + { + "value": "progress", + "label": "Progress" + }, + { + "value": "tree", + "label": "Tree" + }, + { + "value": "pagination", + "label": "Pagination" + }, + { + "value": "badge", + "label": "Badge" + } + ] + }, + { + "value": "notice", + "label": "Notice", + "children": [ + { + "value": "alert", + "label": "Alert" + }, + { + "value": "loading", + "label": "Loading" + }, + { + "value": "message", + "label": "Message" + }, + { + "value": "message-box", + "label": "MessageBox" + }, + { + "value": "notification", + "label": "Notification" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "menu", + "label": "Menu" + }, + { + "value": "tabs", + "label": "Tabs" + }, + { + "value": "breadcrumb", + "label": "Breadcrumb" + }, + { + "value": "dropdown", + "label": "Dropdown" + }, + { + "value": "steps", + "label": "Steps" + } + ] + }, + { + "value": "others", + "label": "Others", + "children": [ + { + "value": "dialog", + "label": "Dialog" + }, + { + "value": "tooltip", + "label": "Tooltip" + }, + { + "value": "popover", + "label": "Popover" + }, + { + "value": "card", + "label": "Card" + }, + { + "value": "carousel", + "label": "Carousel" + }, + { + "value": "collapse", + "label": "Collapse" + } + ] + } + ] + }, + { + "value": "resource", + "label": "Resource", + "children": [ + { + "value": "axure", + "label": "Axure Components" + }, + { + "value": "sketch", + "label": "Sketch Templates" + }, + { + "value": "docs", + "label": "Design Documentation" + } + ] + } + ], + "props": {}, + "modelValue": [] + } + } + }, + "ElCascaderPanel": { + "name": "ElCascaderPanel", + "label": "级联面板", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中项绑定值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter", "JSONSetter"] + }, + { + "name": "options", + "title": "选项的数据源", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "props", + "title": "配置选项", + "defaultValue": "", + "setters": "JSONSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "expand-change" + }, + { + "name": "close" + } + ], + "slots": [ + { + "name": "default", + "params": ["node", "data"] + }, + { + "name": "empty" + } + ], + "snippet": { + "props": { + "options": [ + { + "value": "guide", + "label": "Guide", + "children": [ + { + "value": "disciplines", + "label": "Disciplines", + "children": [ + { + "value": "consistency", + "label": "Consistency" + }, + { + "value": "feedback", + "label": "Feedback" + }, + { + "value": "efficiency", + "label": "Efficiency" + }, + { + "value": "controllability", + "label": "Controllability" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "side nav", + "label": "Side Navigation" + }, + { + "value": "top nav", + "label": "Top Navigation" + } + ] + } + ] + }, + { + "value": "component", + "label": "Component", + "children": [ + { + "value": "basic", + "label": "Basic", + "children": [ + { + "value": "layout", + "label": "Layout" + }, + { + "value": "color", + "label": "Color" + }, + { + "value": "typography", + "label": "Typography" + }, + { + "value": "icon", + "label": "Icon" + }, + { + "value": "button", + "label": "Button" + } + ] + }, + { + "value": "form", + "label": "Form", + "children": [ + { + "value": "radio", + "label": "Radio" + }, + { + "value": "checkbox", + "label": "Checkbox" + }, + { + "value": "input", + "label": "Input" + }, + { + "value": "input-number", + "label": "InputNumber" + }, + { + "value": "select", + "label": "Select" + }, + { + "value": "cascader", + "label": "Cascader" + }, + { + "value": "switch", + "label": "Switch" + }, + { + "value": "slider", + "label": "Slider" + }, + { + "value": "time-picker", + "label": "TimePicker" + }, + { + "value": "date-picker", + "label": "DatePicker" + }, + { + "value": "datetime-picker", + "label": "DateTimePicker" + }, + { + "value": "upload", + "label": "Upload" + }, + { + "value": "rate", + "label": "Rate" + }, + { + "value": "form", + "label": "Form" + } + ] + }, + { + "value": "data", + "label": "Data", + "children": [ + { + "value": "table", + "label": "Table" + }, + { + "value": "tag", + "label": "Tag" + }, + { + "value": "progress", + "label": "Progress" + }, + { + "value": "tree", + "label": "Tree" + }, + { + "value": "pagination", + "label": "Pagination" + }, + { + "value": "badge", + "label": "Badge" + } + ] + }, + { + "value": "notice", + "label": "Notice", + "children": [ + { + "value": "alert", + "label": "Alert" + }, + { + "value": "loading", + "label": "Loading" + }, + { + "value": "message", + "label": "Message" + }, + { + "value": "message-box", + "label": "MessageBox" + }, + { + "value": "notification", + "label": "Notification" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "menu", + "label": "Menu" + }, + { + "value": "tabs", + "label": "Tabs" + }, + { + "value": "breadcrumb", + "label": "Breadcrumb" + }, + { + "value": "dropdown", + "label": "Dropdown" + }, + { + "value": "steps", + "label": "Steps" + } + ] + }, + { + "value": "others", + "label": "Others", + "children": [ + { + "value": "dialog", + "label": "Dialog" + }, + { + "value": "tooltip", + "label": "Tooltip" + }, + { + "value": "popover", + "label": "Popover" + }, + { + "value": "card", + "label": "Card" + }, + { + "value": "carousel", + "label": "Carousel" + }, + { + "value": "collapse", + "label": "Collapse" + } + ] + } + ] + }, + { + "value": "resource", + "label": "Resource", + "children": [ + { + "value": "axure", + "label": "Axure Components" + }, + { + "value": "sketch", + "label": "Sketch Templates" + }, + { + "value": "docs", + "label": "Design Documentation" + } + ] + } + ], + "props": {}, + "modelValue": [] + } + } + }, + "ElCheckbox": { + "name": "ElCheckbox", + "label": "多选框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/checkbox.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中项绑定值", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "label", + "title": "选中状态的值,只有在绑定对象类型为 array 时有效。 如果没有 value, label则作为value使用", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "value", + "title": "选中状态的值(只有在checkbox-group或者绑定对象类型为array时有效)", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter", "JSONSetter"] + }, + { + "name": "trueValue", + "title": "选中时的值", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "falseValue", + "title": "没有选中时的值", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "border", + "title": "是否显示边框", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "title": "Checkbox 的尺寸", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "checked", + "title": "当前是否勾选", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "indeterminate", + "defaultValue": false, + "title": "设置 indeterminate 状态,只负责样式控制", + "setters": "BooleanSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "label": "tabindex", + "title": "输入框的 tabindex", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "id", + "label": "id", + "title": "input id", + "setters": "StringSetter" + }, + { + "name": "aria-controls", + "title": "与 aria-control一致, 当 indeterminate为 true时生效", + "setters": "BooleanSetter" + }, + { + "name": "trueLabel", + "title": "选中时的值(deprecated)", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "falseLabel", + "title": "没有选中时的值(deprecated)", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "controls(deprecated)", + "title": "与 aria-control一致, 当 indeterminate为 true时生效", + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "update:modelValue" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "label": "选项一", + "value": 1 + } + } + }, + "ElCheckboxGroup": { + "name": "ElCheckboxGroup", + "label": "多选框组", + "childIncludes": ["ElCheckbox", "ElCheckboxButton"], + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "绑定值", + "defaultValue": [], + "setters": "JSONSetter" + }, + { + "name": "size", + "title": "多选框组尺寸", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "min", + "title": "可被勾选的 checkbox 的最小数量", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "max", + "title": "可被勾选的 checkbox 的最大数量", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "aria-label", + "title": "原生 aria-label属性", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "textColor", + "title": "当按钮为活跃状态时的字体颜色", + "defaultValue": "#ffffff", + "setters": "ColorSetter" + }, + { + "name": "fill", + "defaultValue": "#409EFF", + "title": "当按钮为活跃状态时的边框和背景颜色", + "setters": "ColorSetter" + }, + { + "name": "tag", + "defaultValue": "div", + "title": "复选框组元素标签", + "setters": "StringSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "setters": "BooleanSetter" + }, + { + "name": "label", + "title": "原生 aria-label属性", + "defaultValue": "", + "setters": "StringSetter" + } + ], + "events": ["change", "update:modelValue"], + "slots": ["default"], + "snippet": { + "children": [ + { + "name": "ElCheckbox", + "props": { + "label": "选项一", + "value": "1" + } + }, + { + "name": "ElCheckbox", + "props": { + "label": "选项二", + "value": "2" + } + }, + { + "name": "ElCheckbox", + "props": { + "label": "选项三", + "value": "3" + } + } + ] + } + }, + "ElCheckboxButton": { + "name": "ElCheckboxButton", + "label": "按钮样式的多选组合", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中状态的值,只有在绑定对象类型为 array 时有效。", + "defaultValue": [], + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "JSONSetter"] + }, + { + "name": "label", + "title": "选中状态的值,只有在绑定对象类型为 array 时有效。 如果没有 value, label则作为value使用", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "JSONSetter"] + }, + { + "name": "trueValue", + "title": "选中时的值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "falseValue", + "title": "没有选中时的值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "name", + "title": "原生 name 属性", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "checked", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "trueLabel", + "title": "选中时的值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "falseLabel", + "title": "没有选中时的值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "slots": ["default"], + "snippet": { + "props": { + "label": "按钮选项" + } + } + }, + "ElCollapse": { + "name": "ElCollapse", + "label": "折叠面板", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/collapse.html", + "childIncludes": ["ElCollapseItem"], + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "title": "当前激活的面板(如果是手风琴模式,绑定值类型需要为string,否则为array)", + "setters": ["InputSetter", "ArraySetter", "JSONSetter"] + }, + { + "name": "accordion", + "defaultValue": false, + "title": "是否手风琴模式", + "setters": "BooleanSetter" + } + ], + "events": ["change"], + "slots": ["default"], + "snippet": { + "children": [ + { + "name": "ElCollapseItem", + "children": "面板内容", + "props": { + "title": "面板标题" + }, + "directives": [ + { + "name": "vFor", + "value": { + "type": "JSExpression", + "value": "3" + } + } + ] + } + ] + } + }, + "ElCollapseItem": { + "name": "ElCollapseItem", + "label": "折叠面板子项", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "name", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "icon", + "defaultValue": "ArrowRight", + "setters": "StringSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": ["change"], + "slots": [ + { + "name": "default" + }, + { + "name": "title" + }, + { + "name": "icon" + } + ], + "snippet": { + "children": "面板内容", + "props": { + "title": "面板标题" + } + } + }, + "ElColorPicker": { + "name": "ElColorPicker", + "label": "取色器", + "categoryId": "form", + "childIncludes": false, + "doc": "https://element-plus.org/zh-CN/component/color-picker.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中项绑定值", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "showAlpha", + "title": "是否支持透明度选择", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "colorFormat", + "title": "写入 v-model 的颜色的格式", + "defaultValue": "", + "options": ["hsl", "hsv", "hex", "rgb"], + "setters": "SelectSetter" + }, + { + "name": "popperClass", + "title": "ColorPicker 下拉框的类名", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "predefine", + "title": "预定义颜色", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "validateEvent", + "title": "输入时是否触发表单的校验", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "label": "tabindex", + "title": "ColorPicker 的 tabindex", + "setters": ["StringSetter", "NumberSetter"], + "defaultValue": 0 + }, + { + "name": "aria-label", + "title": "ColorPicker 的 aria-label", + "setters": "StringSetter" + }, + { + "name": "id", + "title": "ColorPicker 的 id", + "setters": "StringSetter" + }, + { + "name": "teleported", + "title": "是否将 popover 的下拉列表渲染至 body 下", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "label", + "title": "ColorPicker 的 aria-label(deprecated)", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "active-change" + }, + { + "name": "update:modelValue" + }, + { + "name": "focus" + }, + { + "name": "blur" + } + ] + }, + "ElConfigProvider": { + "name": "ElConfigProvider", + "label": "全局配置", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/config-provider.html", + "props": [ + { + "name": "locale", + "label": "locale", + "title": "翻译文本对象", + "setters": "ObjectSetter" + }, + { + "name": "size", + "label": "size", + "title": "全局组件大小", + "setters": "SelectSetter", + "options": ["large", "default", "small"], + "defaultValue": "default" + }, + { + "name": "zIndex", + "label": "zIndex", + "title": "全局初始化 zIndex 的值", + "setters": "NumberSetter" + }, + { + "name": "namespace", + "label": "namespace", + "title": "全局组件类名称前缀", + "setters": "StringSetter", + "defaultValue": "el" + }, + { + "name": "button", + "label": "button", + "title": "按钮相关配置", + "setters": "ObjectSetter", + "defaultValue": { + "autoInsertSpace": false + } + }, + { + "name": "message", + "label": "message", + "title": "消息相关配置", + "setters": "ObjectSetter" + }, + { + "name": "experimentalFeatures", + "label": "experimentalFeatures", + "title": "将要添加的实验阶段的功能,所有功能都是默认设置为 false", + "setters": "ObjectSetter" + } + ], + "slots": ["default"], + "package": "element-plus" + }, + "ElContainer": { + "name": "ElContainer", + "label": "布局容器", + "categoryId": "layout", + "doc": "https://element-plus.org/zh-CN/component/container.html", + "package": "element-plus", + "props": [ + { + "name": "direction", + "defaultValue": "", + "setters": "SelectSetter", + "options": ["horizontal", "vertical"] + } + ], + "slots": ["default"], + "snippet": { + "props": { + "style": { + "width": "100%", + "height": "100%" + } + } + } + }, + "ElHeader": { + "name": "ElHeader", + "parentIncludes": ["ElContainer"], + "label": "顶栏容器", + "categoryId": "layout", + "package": "element-plus", + "props": [ + { + "name": "height", + "defaultValue": "60px", + "setters": ["InputSetter"] + } + ] + }, + "ElAside": { + "name": "ElAside", + "parentIncludes": ["ElContainer"], + "label": "侧边栏容器", + "categoryId": "layout", + "package": "element-plus", + "props": [ + { + "name": "width", + "defaultValue": "300px", + "setters": ["InputSetter"] + } + ], + "slots": ["default"] + }, + "ElMain": { + "name": "ElMain", + "parentIncludes": ["ElContainer"], + "label": "主要区域容器", + "categoryId": "layout", + "package": "element-plus" + }, + "ElFooter": { + "name": "ElFooter", + "parentIncludes": ["ElContainer"], + "label": "底栏容器", + "categoryId": "layout", + "package": "element-plus", + "props": [ + { + "name": "height", + "defaultValue": "60px", + "setters": ["InputSetter"] + } + ], + "slots": ["default"] + }, + "ElDatePicker": { + "name": "ElDatePicker", + "label": "日期选择器", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/date-picker.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "绑定值,如果它是数组,长度应该是 2", + "defaultValue": "", + "setters": ["NumberSetter", "StringSetter", "ArraySetter", "ExpressionSetter"] + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "editable", + "title": "文本框可输入", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "startPlaceholder", + "defaultValue": "", + "title": "范围选择时开始日期的占位内容", + "setters": "InputSetter" + }, + { + "name": "endPlaceholder", + "defaultValue": "", + "title": "范围选择时结束日期的占位内容", + "setters": "InputSetter" + }, + { + "name": "type", + "defaultValue": "date", + "title": "显示类型", + "options": [ + "year", + "years", + "month", + "months", + "date", + "dates", + "datetime", + "week", + "datetimerange", + "daterange", + "monthrange", + "yearrange" + ], + "setters": "SelectSetter" + }, + { + "name": "format", + "title": "显示在输入框中的格式", + "defaultValue": "YYYY-MM-DD", + "setters": "InputSetter" + }, + { + "name": "popperClass", + "title": "DatePicker 下拉框的类名", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "popper-options", + "title": "自定义 popper 选项", + "defaultValue": "", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "rangeSeparator", + "defaultValue": "-", + "title": "选择范围时的分隔符", + "setters": "InputSetter" + }, + { + "name": "defaultValue", + "title": "可选,选择器打开时默认显示的时间", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "defaultTime", + "title": "范围选择时选中日期所使用的当日内具体时刻", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "valueFormat", + "title": "可选,绑定值的格式。 不指定则绑定值为 Date 对象", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "id", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "unlinkPanels", + "title": "在范围选择器里取消两个日期面板之间的联动", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "prefixIcon", + "defaultValue": "Date", + "title": "自定义前缀图标", + "setters": "InputSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "title": "自定义清除图标", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "setters": "BooleanSetter" + }, + { + "name": "disabledDate", + "title": "一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参数。 应该返回一个 Boolean 值。", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "shortcuts", + "defaultValue": "", + "title": "设置快捷选项,需要传入数组对象", + "setters": "JSONSetter" + }, + { + "name": "cellClassName", + "defaultValue": "", + "title": "设置自定义类名", + "setters": "FunctionSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "title": "是否将 date-picker 的下拉列表插入至 body 元素", + "setters": "BooleanSetter" + }, + { + "name": "empty-values", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "value-on-clear", + "title": "清空选项的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "fallback-placements", + "title": "Tooltip 可用的 positions", + "setters": "ArraySetter" + }, + { + "name": "placement", + "title": "下拉框出现的位置", + "defaultValue": "bottom", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ] + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "clear" + }, + { + "name": "calendar-change" + }, + { + "name": "panel-change" + }, + { + "name": "visible-change" + }, + { + "name": "update:modelValue" + } + ], + "slots": [ + { + "name": "default", + "params": ["cell"] + }, + { + "name": "range-separator" + }, + { + "name": "prev-month" + }, + { + "name": "next-month" + }, + { + "name": "prev-year" + }, + { + "name": "next-year" + } + ] + }, + "ElDateTimePicker": { + "name": "ElDateTimePicker", + "label": "日期时间选择器", + "alias": "ElDatePicker", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/datetime-picker.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["NumberSetter", "StringSetter", "ExpressionSetter"] + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "editable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "startPlaceholder", + "defaultValue": "", + "title": "范围选择时开始日期的占位内容", + "setters": "StringSetter" + }, + { + "name": "endPlaceholder", + "defaultValue": "", + "title": "范围选择时结束日期的占位内容", + "setters": "InputSetter" + }, + { + "name": "arrowControl", + "title": "是否使用箭头进行时间选择", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "type", + "defaultValue": "date", + "title": "显示类型", + "options": [ + "year", + "month", + "date", + "dates", + "datetime", + "week", + "datetimerange", + "daterange", + "monthrange" + ], + "setters": "SelectSetter" + }, + { + "name": "format", + "title": "显示在输入框中的格式", + "defaultValue": "YYYY-MM-DD HH:mm:ss", + "setters": "StringSetter" + }, + { + "name": "popperClass", + "title": "DateTimePicker 下拉框的类名", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "rangeSeparator", + "defaultValue": "-", + "title": "选择范围时的分隔符", + "setters": "StringSetter" + }, + { + "name": "defaultValue", + "title": "可选,选择器打开时默认显示的时间", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "defaultTime", + "title": "选择日期后的默认时间值。 如未指定则默认时间值为 00:00:00", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "valueFormat", + "title": "可选,绑定值的格式。 不指定则绑定值为 Date 对象", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "dateFormat", + "defaultValue": "", + "setters": "StringSetter", + "title": "时间选择器下拉列表中显示的日期格式" + }, + { + "name": "timeFormat", + "defaultValue": "", + "setters": "StringSetter", + "title": "时间选择器下拉列表中显示的时间格式" + }, + { + "name": "id", + "defaultValue": "", + "setters": ["StringSetter", "ArraySetter", "ExpressionSetter"] + }, + { + "name": "name", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "unlinkPanels", + "title": "在范围选择器里取消两个日期面板之间的联动", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "prefixIcon", + "defaultValue": "Date", + "title": "自定义前缀图标", + "setters": "InputSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "title": "自定义清除图标", + "setters": "InputSetter" + }, + { + "name": "shortcuts", + "defaultValue": "", + "title": "设置快捷选项,需要传入数组对象", + "setters": "JSONSetter" + }, + { + "name": "disabledDate", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "cellClassName", + "defaultValue": "", + "title": "设置自定义类名", + "setters": "FunctionSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "title": "设置自定义类名", + "setters": "BooleanSetter" + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "showNow", + "title": "是否显示 now 按钮", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "clear" + }, + { + "name": "calendar-change" + }, + { + "name": "visible-change" + }, + { + "name": "update:modelValue" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "range-separator" + }, + { + "name": "prev-month" + }, + { + "name": "next-month" + }, + { + "name": "prev-year" + }, + { + "name": "next-year" + } + ], + "snippet": { + "props": { + "type": "datetime", + "placeholder": "Select date and time" + } + } + }, + "ElDescriptions": { + "name": "ElDescriptions", + "label": "描述列表", + "categoryId": "data", + "package": "element-plus", + "doc": "https://element-plus.org/zh-CN/component/descriptions.html", + "props": [ + { + "name": "border", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "column", + "defaultValue": 3, + "setters": "NumberSetter" + }, + { + "name": "direction", + "defaultValue": "horizontal", + "options": ["vertical", "horizontal"], + "setters": "SelectSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["", "large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "extra", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "slots": ["default", "title", "extra"], + "snippet": { + "props": { + "border": true + }, + "children": [ + { + "name": "ElDescriptionsItem", + "children": "kooriookami", + "props": { + "label": "Username" + } + }, + { + "name": "ElDescriptionsItem", + "children": "18100000000", + "props": { + "label": "Telephone" + } + }, + { + "name": "ElDescriptionsItem", + "children": "Suzhou", + "props": { + "label": "Place" + } + }, + { + "name": "ElDescriptionsItem", + "children": "No.1188, Wuzhong Avenue, Wuzhong District, Suzhou, Jiangs Province", + "props": { + "label": "Address" + } + } + ] + } + }, + "ElDescriptionsItem": { + "name": "ElDescriptionsItem", + "label": "描述列表子项", + "categoryId": "data", + "parentIncludes": ["ElDescriptions"], + "package": "element-plus", + "props": [ + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "span", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "rowspan", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "width", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "min-width", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "align", + "defaultValue": "left", + "options": ["left", "center", "right"], + "setters": "SelectSetter" + }, + { + "name": "label-align", + "defaultValue": "", + "options": ["left", "center", "right"], + "setters": "SelectSetter" + }, + { + "name": "class-name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "label-class-name", + "defaultValue": "", + "label": "标题类名", + "setters": "InputSetter" + } + ], + "slots": ["default", "label"], + "snippet": { + "children": "内容", + "props": { + "label": "标题" + } + } + }, + "ElDialog": { + "name": "ElDialog", + "label": "对话框", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/dialog.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "width", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "fullscreen", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "top", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "modal", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "modalClass", + "label": "modalClass", + "title": "遮罩的自定义类名", + "setters": "StringSetter" + }, + { + "name": "appendToBody", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "appendTo", + "label": "appendTo", + "title": "Dialog 挂载到哪个 DOM 元素 将覆盖 append-to-body", + "setters": "StringSetter", + "defaultValue": "body" + }, + { + "name": "lockScroll", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "openDelay", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "closeDelay", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "closeOnClickModal", + "label": "点击关闭", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "closeOnPressEscape", + "label": "ESC键关闭", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "showClose", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "beforeClose", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "draggable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "overflow", + "label": "overflow", + "title": "拖动范围可以超出可视区", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "center", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "alignCenter", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "destroyOnClose", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "closeIcon", + "label": "closeIcon", + "title": "自定义关闭图标", + "setters": ["StringSetter", "IconSetter"] + }, + { + "name": "z-index", + "label": "z-index", + "title": "和原生的 CSS 的 z-index 相同,改变 z 轴的顺序", + "setters": "NumberSetter" + }, + { + "name": "headerAriaLevel", + "label": "headerAriaLevel", + "title": "header 的 aria-level 属性", + "setters": "StringSetter", + "defaultValue": 2 + }, + { + "name": "customClass", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "events": [ + { + "name": "open" + }, + { + "name": "opened" + }, + { + "name": "close" + }, + { + "name": "closed" + }, + { + "name": "open-auto-focus" + }, + { + "name": "close-auto-focus" + }, + { + "name": "update:modelValue" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "header" + }, + { + "name": "footer" + }, + { + "name": "title" + } + ], + "snippet": { + "name": "ElDialog", + "children": "对话框弹窗内容", + "props": { + "title": "标题", + "modelValue": true + } + } + }, + "ElDivider": { + "name": "ElDivider", + "label": "分割线", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/divider.html", + "package": "element-plus", + "props": [ + { + "name": "direction", + "defaultValue": "horizontal", + "setters": "SelectSetter", + "options": ["horizontal", "vertical"] + }, + { + "name": "borderStyle", + "defaultValue": "solid", + "setters": "InputSetter" + }, + { + "name": "contentPosition", + "defaultValue": "center", + "setters": "SelectSetter", + "options": ["left", "right", "center"] + } + ], + "slots": ["default"], + "snippet": { + "name": "ElDivider", + "children": "分割线" + } + }, + "ElDrawer": { + "name": "ElDrawer", + "label": "抽屉", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/drawer.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "appendToBody", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "appendTo", + "defaultValue": "body", + "setters": "StringSetter" + }, + { + "name": "lockScroll", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "beforeClose", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "closeOnClickModal", + "label": "点击蒙层关闭", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "closOonPressEscape", + "label": "ESC键关闭", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "openDelay", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "closeDelay", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "destroyOnClose", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "modal", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "direction", + "defaultValue": "rtl", + "setters": "SelectSetter", + "options": ["rtl", "ltr", "ttb", "btt"] + }, + { + "name": "showClose", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "30%", + "title": "Drawer 窗体的大小, 当使用 number 类型时, 以像素为单位, 当使用 string 类型时, 请传入 x%, 否则便会以 number 类型解释", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "withHeader", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "modalClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "zIndex", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "headerAriaLevel", + "label": "headerAriaLevel", + "title": "header 的 aria-level 属性", + "setters": "StringSetter", + "defaultValue": 2 + }, + { + "name": "customClass", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "events": [ + { + "name": "open" + }, + { + "name": "opened" + }, + { + "name": "close" + }, + { + "name": "closed" + }, + { + "name": "open-auto-focus" + }, + { + "name": "close-auto-focus" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "header" + }, + { + "name": "footer" + }, + { + "name": "title" + } + ], + "snippet": { + "name": "ElDrawer", + "children": "抽屉内容", + "props": { + "title": "标题", + "modelValue": true + } + } + }, + "ElDropdown": { + "name": "ElDropdown", + "label": "下拉菜单", + "categoryId": "nav", + "doc": "https://element-plus.org/zh-CN/component/dropdown.html", + "package": "element-plus", + "props": [ + { + "name": "type", + "defaultValue": "", + "options": ["", "default", "primary", "success", "warning", "info", "danger", "text"], + "setters": "SelectSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["large", "default", "small"] + }, + { + "name": "maxHeight", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "splitButton", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "defaultValue": "bottom", + "setters": "SelectSetter", + "options": ["top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end"] + }, + { + "name": "trigger", + "defaultValue": "hover", + "setters": "SelectSetter", + "options": ["hover", "click", "contextmenu"] + }, + { + "name": "triggerKeys", + "title": "指定键盘上哪些按键可以触发操作", + "defaultValue": ["Enter", "Space", "ArrowDown", "NumpadEnter"], + "setters": "ArraySetter" + }, + { + "name": "hideOnClick", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "showTimeout", + "defaultValue": 150, + "setters": "NumberSetter" + }, + { + "name": "hideTimeout", + "defaultValue": 150, + "setters": "NumberSetter" + }, + { + "name": "role", + "defaultValue": "menu", + "setters": "InputSetter" + }, + { + "name": "tabindex", + "defaultValue": 0, + "setters": ["NumberSetter", "StringSetter"] + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "popperOptions", + "defaultValue": { + "modifiers": [ + { + "name": "computeStyles", + "options": { + "gpuAcceleration": false + } + } + ] + }, + "setters": "JSONSetter" + }, + { + "name": "teleported", + "label": "teleported", + "title": "是否将下拉列表插入至 body 元素", + "setters": "BooleanSetter", + "defaultValue": true + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "dropdown" + } + ], + "events": [ + { + "name": "click" + }, + { + "name": "command" + }, + { + "name": "visible-change" + } + ], + "snippet": { + "name": "ElDropdown", + "children": [ + { + "name": "ElButton", + "children": [ + { + "name": "component", + "props": { + "is": "span" + }, + "children": "下拉菜单" + }, + { + "name": "component", + "props": { + "is": "span" + }, + "children": " V" + } + ] + }, + { + "name": "ElDropdownMenu", + "slot": "dropdown", + "children": [ + { + "name": "ElDropdownItem", + "children": "Action 1" + }, + { + "name": "ElDropdownItem", + "children": "Action 2" + }, + { + "name": "ElDropdownItem", + "children": "Action 3" + } + ] + } + ] + } + }, + "ElDropdownMenu": { + "name": "ElDropdownMenu", + "label": "下拉菜单Menu", + "categoryId": "nav", + "package": "element-plus", + "slots": ["default"] + }, + "ElDropdownItem": { + "name": "ElDropdownItem", + "childIncludes": true, + "label": "下拉菜单项", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "command", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "JSONSetter"] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "divided", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "icon", + "defaultValue": "", + "setters": ["InputSetter"] + } + ], + "slots": ["default", "icon"], + "snippet": { + "name": "ElDropdownItem", + "children": "下拉选项" + } + }, + "ElEmpty": { + "name": "ElEmpty", + "label": "空状态", + "doc": "https://element-plus.org/zh-CN/component/empty.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "image", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "imageSize", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "description", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "image" + }, + { + "name": "description" + } + ] + }, + "ElForm": { + "name": "ElForm", + "label": "表单", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/form.html", + "package": "element-plus", + "props": [ + { + "name": "model", + "title": "表单数据对象", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "rules", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "inline", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "labelPosition", + "defaultValue": "right", + "options": ["left", "right", "top"], + "setters": "SelectSetter" + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "labelSuffix", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "hideRequiredAsterisk", + "defaultValue": false, + "title": "是否显示必填字段的标签旁边的红色星号", + "setters": "BooleanSetter" + }, + { + "name": "requireAsteriskPosition", + "defaultValue": "left", + "title": "星号的位置", + "options": ["left", "right"], + "setters": "SelectSetter" + }, + { + "name": "showMessage", + "defaultValue": true, + "title": "是否显示校验错误信息", + "setters": "BooleanSetter" + }, + { + "name": "inlineMessage", + "defaultValue": false, + "title": "是否以行内形式展示校验信息", + "setters": "BooleanSetter" + }, + { + "name": "statusIcon", + "defaultValue": false, + "title": "是否在输入框中显示校验结果反馈图标", + "setters": "BooleanSetter" + }, + { + "name": "validateOnRuleChange", + "defaultValue": true, + "title": "是否在 rules 属性改变后立即触发一次验证", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollToError", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollIntoViewOptions", + "defaultValue": "", + "setters": ["ExpressionSetter", "BooleanSetter"] + } + ], + "events": [ + { + "name": "validate" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElForm", + "props": { + "labelWidth": "80px" + }, + "children": [ + { + "name": "ElFormItem", + "props": { + "label": "表单项" + }, + "children": [ + { + "name": "ElInput" + } + ] + }, + { + "name": "ElFormItem", + "props": { + "label": " " + }, + "children": [ + { + "name": "ElButton", + "props": { + "type": "primary" + }, + "children": "确定" + } + ] + } + ] + } + }, + "ElFormItem": { + "name": "ElFormItem", + "label": "表单项", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "prop", + "defaultValue": "", + "setters": ["InputSetter", "ArraySetter"] + }, + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "labelPosition", + "defaultValue": "", + "setters": "SelectSetter", + "options": ["left", "right", "top"] + }, + { + "name": "labelWidth", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "required", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "rules", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "error", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "showMessage", + "defaultValue": true, + "title": "是否显示校验错误信息", + "label": "错误信息", + "setters": "BooleanSetter" + }, + { + "name": "inlineMessage", + "defaultValue": false, + "title": "是否在行内显示校验信息", + "label": "校验信息", + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "for", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "validateStatus", + "title": "formitem 校验的状态", + "options": ["", "error", "validating", "success"], + "setters": "SelectSetter" + } + ], + "slots": ["default", "label", "error"], + "snippet": { + "props": { + "label": "表单项" + }, + "children": [ + { + "name": "ElInput" + } + ] + } + }, + "ElImage": { + "name": "ElImage", + "label": "图片", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/image.html", + "childIncludes": false, + "package": "element-plus", + "props": [ + { + "name": "src", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "fit", + "defaultValue": "", + "options": ["", "fill", "contain", "cover", "none", "scale-down"], + "setters": "SelectSetter" + }, + { + "name": "hideOnClickModal", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": "", + "options": ["eager", "lazy"], + "setters": "SelectSetter" + }, + { + "name": "lazy", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollContainer", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "alt", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "referrerPolicy", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "crossorigin", + "label": "crossorigin", + "title": "原生属性 crossorigin", + "setters": "SelectSetter", + "options": ["", "anonymous", "use-credentials"] + }, + { + "name": "previewSrcList", + "defaultValue": "", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "zIndex", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "initialIndex", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "close-on-press-escape", + "label": "close-on-press-escape", + "defaultValue": true, + "title": "是否可以通过按下 ESC 关闭 Image Viewer", + "setters": "BooleanSetter" + }, + { + "name": "previewTeleported", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "infinite", + "defaultValue": true, + "setters": "BooleanSetter", + "title": "是否可以无限循环预览" + }, + { + "name": "zoomRate", + "defaultValue": 1.2, + "setters": { + "name": "NumberSetter", + "props": { + "precision": 1 + } + }, + "title": "图像查看器缩放事件的缩放速率" + }, + { + "name": "minScale", + "defaultValue": 0.2, + "setters": { + "name": "NumberSetter", + "props": { + "precision": 1 + } + }, + "title": "图像查看器缩放事件的最小缩放比例" + }, + { + "name": "maxScale", + "defaultValue": 7, + "setters": { + "name": "NumberSetter", + "props": { + "precision": 1 + } + }, + "title": "图像查看器缩放事件的最大缩放比例" + } + ], + "events": ["load", "error", "switch", "close", "show"], + "slots": ["placeholder", "error", "viewer"], + "snippet": { + "props": { + "style": { + "width": "100px", + "height": "100px" + }, + "src": "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg", + "previewSrcList": [ + "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg", + "https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg", + "https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg", + "https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg", + "https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg", + "https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg", + "https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg" + ] + } + } + }, + "ElInput": { + "name": "ElInput", + "label": "输入框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/input.html", + "props": [ + { + "name": "type", + "defaultValue": "text", + "options": ["text", "textarea"], + "setters": ["SelectSetter", "InputSetter"] + }, + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "maxlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "minlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "showWordLimit", + "defaultValue": false, + "title": "是否显示输入字数统计,只在 type = \"text\" 或 type = \"textarea\" 时有效", + "label": "字数统计", + "setters": "BooleanSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "formatter", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "parser", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "showPassword", + "defaultValue": false, + "title": "是否显示切换密码图标", + "label": "密码图标", + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "prefix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "suffix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rows", + "defaultValue": 2, + "setters": "NumberSetter" + }, + { + "name": "autosize", + "defaultValue": false, + "setters": ["BooleanSetter", "JSONStter"] + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "max", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "min", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "step", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "resize", + "defaultValue": "", + "options": ["none", "both", "horizontal", "vertical"], + "setters": "InputSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "form", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "aria-label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "label": "表单校验", + "setters": "BooleanSetter" + }, + { + "name": "inputStyle", + "defaultValue": {}, + "setters": ["JSONSetter"] + } + ], + "events": [ + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "change" + }, + { + "name": "input" + }, + { + "name": "clear" + }, + { + "name": "update:modelValue" + } + ], + "slots": ["prefix", "suffix", "prepend", "append"], + "package": "element-plus" + }, + "ElInputNumber": { + "name": "ElInputNumber", + "label": "数字输入框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/input-number.html", + "childIncludes": false, + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "min", + "defaultValue": null, + "setters": "NumberSetter" + }, + { + "name": "max", + "defaultValue": null, + "setters": "NumberSetter" + }, + { + "name": "step", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "stepStrictly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "precision", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "controls", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "controlsPosition", + "defaultValue": "", + "title": "控制按钮位置", + "label": "按钮位置", + "options": ["", "right"], + "setters": "SelectSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "ariaLabel", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "valueOnClear", + "defaultValue": "", + "options": ["min", "max"], + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "slots": [ + { + "name": "decreaseIcon" + }, + { + "name": "increaseIcon" + }, + { + "name": "prefix" + }, + { + "name": "suffix" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "update:modelValue" + } + ] + }, + "ElInputTag": { + "name": "ElInputTag", + "label": "标签输入框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/input-tag.html", + "props": [ + { + "name": "modelValue", + "setters": "ArraySetter" + }, + { + "name": "max", + "title": "可添加标签的最大数量", + "setters": "NumberSetter" + }, + { + "name": "tagType", + "title": "标签类型", + "defaultValue": "info", + "setters": "SelectSetter", + "options": ["primary", "success", "info", "warning", "danger"] + }, + { + "name": "tagEffect", + "title": "标签效果", + "defaultValue": "light", + "setters": "SelectSetter", + "options": ["light", "dark", "plain"] + }, + { + "name": "trigger", + "title": "触发输入标签的按键", + "defaultValue": "Enter", + "setters": "SelectSetter", + "options": ["Enter", "Space"] + }, + { + "name": "draggable", + "title": "是否可以拖动标签", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "setters": "SelectSetter", + "defaultValue": "default", + "options": ["large", "default", "small"] + }, + { + "name": "clearable", + "title": "是否显示清除按钮", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "validateEvent", + "title": "是否触发表单验证", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "id", + "setters": "StringSetter" + }, + { + "name": "tabindex", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "maxlength", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "minlength", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "placeholder", + "setters": "StringSetter" + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "StringSetter" + }, + { + "name": "ariaLabel", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "input" + }, + { + "name": "add-tag" + }, + { + "name": "remove-tag" + }, + { + "name": "focus" + }, + { + "name": "blur" + }, + { + "name": "clear" + }, + { + "name": "update:modelValue" + } + ], + "slots": [ + { + "name": "tag", + "params": ["value", "index"] + }, + { + "name": "prefix" + }, + { + "name": "suffix" + } + ], + "snippet": { + "props": { + "modelValue": ["1", "2"] + } + }, + "package": "element-plus" + }, + "ElMention": { + "name": "ElMention", + "label": "提及", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/mention.html#api", + "props": [ + { + "name": "options", + "title": "提及选项列表", + "defaultValue": [], + "setters": "ArraySetter" + }, + { + "name": "prefix", + "title": "触发字段的前缀。 字符串长度必须且只能为 1", + "defaultValue": "@", + "setters": ["StringSetter", "ArraySetter"] + }, + { + "name": "split", + "title": "用于拆分提及的字符。 字符串长度必须且只能为 1\t", + "defaultValue": " ", + "setters": "StringSetter" + }, + { + "name": "filterOption", + "title": "定制筛选器选项逻辑", + "setters": ["BooleanSetter", "FunctionSetter"] + }, + { + "name": "placement", + "title": "设置弹出位置", + "defaultValue": "bottom", + "options": ["top", "bottom"], + "setters": "SelectSetter" + }, + { + "name": "showArrow", + "title": "下拉菜单的内容是否有箭头", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "title": "下拉面板偏移量", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "whole", + "title": "当退格键被按下做删除操作时,是否将提及部分作为整体删除", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "checkIsWhole", + "title": "当退格键被按下做删除操作时,检查是否将提及部分作为整体删除", + "setters": "FunctionSetter" + }, + { + "name": "loading", + "title": "提及的下拉面板是否处于加载状态", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "modelValue", + "title": "输入值", + "setters": "StringSetter" + }, + { + "name": "popperClass", + "title": "自定义浮层类名", + "setters": "StringSetter" + }, + { + "name": "popperOptions", + "title": "参数", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "type", + "defaultValue": "text", + "options": ["text", "textarea"], + "setters": ["SelectSetter", "InputSetter"] + }, + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "maxlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "minlength", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "showWordLimit", + "defaultValue": false, + "title": "是否显示输入字数统计,只在 type = \"text\" 或 type = \"textarea\" 时有效", + "label": "字数统计", + "setters": "BooleanSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "formatter", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "parser", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "showPassword", + "defaultValue": false, + "title": "是否显示切换密码图标", + "label": "密码图标", + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "large", "small"] + }, + { + "name": "prefix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "suffix-icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rows", + "defaultValue": 2, + "setters": "NumberSetter" + }, + { + "name": "autosize", + "defaultValue": false, + "setters": ["BooleanSetter", "JSONStter"] + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "max", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "min", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "step", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "resize", + "defaultValue": "", + "options": ["none", "both", "horizontal", "vertical"], + "setters": "InputSetter" + }, + { + "name": "autofocus", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "form", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "aria-label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "title": "输入时是否触发表单的校验", + "label": "表单校验", + "setters": "BooleanSetter" + }, + { + "name": "inputStyle", + "defaultValue": {}, + "setters": ["JSONSetter"] + } + ], + "events": [ + { + "name": "update:modelValue" + }, + { + "name": "search" + }, + { + "name": "select" + }, + { + "name": "input" + }, + { + "name": "blur" + }, + { + "name": "focus" + }, + { + "name": "change" + }, + { + "name": "clear" + } + ], + "slots": ["label", "loading", "header", "footer", "prefix", "suffix", "prepend", "append"], + "snippet": { + "props": { + "options": [ + { + "label": "Fuphoenixes", + "value": "Fuphoenixes" + }, + { + "label": "kooriookami", + "value": "kooriookami" + }, + { + "label": "Jeremy", + "value": "Jeremy" + }, + { + "label": "btea", + "value": "btea" + } + ], + "modelValue": "@" + } + }, + "package": "element-plus" + }, + "ElRow": { + "name": "ElRow", + "label": "布局行", + "categoryId": "layout", + "doc": "https://element-plus.org/zh-CN/component/layout.html", + "package": "element-plus", + "props": [ + { + "name": "gutter", + "defaultValue": 0, + "label": "栅格间隔", + "setters": "NumberSetter" + }, + { + "name": "justify", + "defaultValue": "start", + "title": "flex 布局下的水平排列方式", + "options": ["start", "end", "center", "space-around", "space-between", "space-evenly"], + "setters": "SelectSetter" + }, + { + "name": "align", + "defaultValue": "top", + "title": "flex 布局下的垂直排列方式", + "options": ["top", "middle", "bottom"], + "setters": "SelectSetter" + }, + { + "name": "tag", + "defaultValue": "div", + "title": "自定义元素标签", + "setters": "InputSetter" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "gutter": 10 + }, + "children": [ + { + "name": "ElCol", + "props": { + "span": 6 + }, + "children": [ + { + "name": "component", + "props": { + "is": "div", + "style": { + "height": "50px", + "background": "#ecf5ff" + } + } + } + ], + "directives": [ + { + "name": "vFor", + "value": { + "type": "JSExpression", + "value": "4" + } + } + ] + } + ] + } + }, + "ElCol": { + "name": "ElCol", + "label": "布局列", + "categoryId": "layout", + "package": "element-plus", + "parentIncludes": ["ElRow"], + "props": [ + { + "name": "span", + "defaultValue": 24, + "setters": "NumberSetter" + }, + { + "name": "offset", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "push", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "pull", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "xs", + "setters": ["JSONSetter", "NumberSetter"] + }, + { + "name": "sm", + "setters": ["JSONSetter", "NumberSetter"] + }, + { + "name": "md", + "setters": ["JSONSetter", "NumberSetter"] + }, + { + "name": "lg", + "setters": ["JSONSetter", "NumberSetter"] + }, + { + "name": "xl", + "setters": ["JSONSetter", "NumberSetter"] + }, + { + "name": "tag", + "defaultValue": "div", + "title": "自定义元素标签", + "setters": "InputSetter" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "span": 6 + }, + "children": [ + { + "name": "component", + "props": { + "is": "div", + "style": { + "height": "50px", + "background": "#ecf5ff" + } + }, + "children": "Col" + } + ] + } + }, + "ElLink": { + "name": "ElLink", + "label": "链接", + "categoryId": "base", + "doc": "https://element-plus.org/zh-CN/component/link.html", + "props": [ + { + "name": "type", + "defaultValue": "default", + "setters": "SelectSetter", + "options": ["default", "primary", "success", "warning", "danger", "info"] + }, + { + "name": "underline", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "href", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "target", + "label": "target", + "title": "同原生 target 属性", + "setters": "SelectSetter", + "options": ["_blank", "_parent", "_self", "_top"], + "defaultValue": "_self" + }, + { + "name": "icon", + "defaultValue": "", + "setters": "IconSetter" + } + ], + "events": [], + "slots": [ + { + "name": "default" + }, + { + "name": "icon" + } + ], + "snippet": { + "children": "链接文本" + }, + "package": "element-plus" + }, + "ElMenu": { + "name": "ElMenu", + "label": "导航菜单", + "doc": "https://element-plus.org/zh-CN/component/menu.html", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "mode", + "defaultValue": "vertical", + "setters": "SelectSetter", + "options": ["horizontal", "vertical"] + }, + { + "name": "collapse", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "ellipsis", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "ellipsisIcon", + "label": "ellipsisIcon", + "title": "自定义省略图标 (仅在水平模式下可用)", + "setters": "StringSetter" + }, + { + "name": "popperOffset", + "label": "popperOffset", + "title": "弹出层的偏移量(对所有子菜单有效)", + "setters": "NumberSetter", + "defaultValue": 6 + }, + { + "name": "defaultActive", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "defaultOpeneds", + "defaultValue": [], + "setters": "ArraySetter" + }, + { + "name": "uniqueOpened", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "menuTrigger", + "defaultValue": "hover", + "setters": "SelectSetter", + "options": ["hover", "click"] + }, + { + "name": "router", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTransition", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "popperEffect", + "label": "popperEffect", + "title": "Tooltip 主题,内置了 dark / light 两种主题", + "setters": "SelectSetter", + "options": ["dark", "light"], + "defaultValue": "dark" + }, + { + "name": "closeOnClickOutside", + "label": "closeOnClickOutside", + "title": "可选,单击外部时是否折叠菜单", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "popperClass", + "label": "popperClass", + "title": "为 popper 添加类名", + "setters": "StringSetter" + }, + { + "name": "showTimeout", + "label": "showTimeout", + "title": "菜单出现前的延迟", + "setters": "NumberSetter", + "defaultValue": 300 + }, + { + "name": "hideTimeout", + "label": "hideTimeout", + "title": "菜单消失前的延迟", + "setters": "NumberSetter", + "defaultValue": 300 + }, + { + "name": "backgroundColor", + "defaultValue": "#ffffff", + "setters": "ColorSetter" + }, + { + "name": "textColor", + "defaultValue": "#303133", + "setters": "ColorSetter" + }, + { + "name": "activeTextColor", + "defaultValue": "#409EFF", + "setters": "ColorSetter" + } + ], + "events": [ + { + "name": "select" + }, + { + "name": "open" + }, + { + "name": "close" + } + ], + "slots": ["default", "ellipsis-icon"], + "snippet": { + "props": { + "mode": "horizontal" + }, + "children": [ + { + "name": "ElMenuItem", + "children": "菜单项一", + "props": { + "index": "1" + } + }, + { + "name": "ElSubMenu", + "props": { + "index": "2" + }, + "children": [ + { + "name": "component", + "slot": "title", + "props": { + "is": "div" + }, + "children": "子菜单" + }, + { + "name": "ElMenuItem", + "children": "子菜单项一", + "props": { + "index": "2-1" + } + }, + { + "name": "ElMenuItem", + "children": "子菜单项二", + "props": { + "index": "2-2" + } + } + ] + }, + { + "name": "ElMenuItem", + "children": "菜单项三", + "props": { + "index": "3" + } + } + ] + } + }, + "ElSubMenu": { + "name": "ElSubMenu", + "label": "导航子菜单", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "index", + "label": "index *", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "showTimeout", + "setters": "NumberSetter" + }, + { + "name": "hideTimeout", + "setters": "NumberSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "teleported", + "setters": "BooleanSetter" + }, + { + "name": "popperOffset", + "defaultValue": 6, + "setters": "NumberSetter" + }, + { + "name": "expandCloseIcon", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "expandOpenIcon", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "collapseCloseIcon", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "collapseOpenIcon", + "defaultValue": "", + "setters": ["InputSetter"] + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "title" + } + ], + "snippet": { + "children": [ + { + "name": "component", + "slot": "title", + "props": { + "is": "div" + }, + "children": "子菜单" + }, + { + "name": "ElMenuItem", + "children": "子菜单项一" + } + ] + } + }, + "ElMenuItem": { + "name": "ElMenuItem", + "label": "导航菜单项", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "index", + "defaultValue": null, + "setters": "InputSetter" + }, + { + "name": "route", + "defaultValue": "", + "setters": ["StringSetter", "JSONSetter"] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "click" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "title" + } + ], + "snippet": { + "children": "菜单项" + } + }, + "ElMenuItemGroup": { + "name": "ElMenuItemGroup", + "label": "导航菜单组", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "title" + } + ], + "snippet": { + "props": { + "title": "分组一" + }, + "children": [ + { + "name": "ElMenuItem", + "children": "子菜单项一" + }, + { + "name": "ElMenuItem", + "children": "子菜单项一" + } + ] + } + }, + "ElPageHeader": { + "name": "ElPageHeader", + "label": "页头", + "doc": "https://element-plus.org/zh-CN/component/page-header.html", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "icon", + "defaultValue": "Back", + "setters": "InputSetter" + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "content", + "defaultValue": "", + "setters": "InputSetter" + } + ], + "events": [ + { + "name": "back" + } + ], + "slots": [ + { + "name": "icon" + }, + { + "name": "title" + }, + { + "name": "content" + }, + { + "name": "extra" + }, + { + "name": "breadcrumb" + }, + { + "name": "default" + } + ], + "snippet": { + "name": "ElPageHeader", + "children": [ + { + "name": "component", + "slot": "content", + "props": { + "is": "span" + }, + "children": "Title" + } + ] + } + }, + "ElPagination": { + "name": "ElPagination", + "label": "分页", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/pagination.html", + "package": "element-plus", + "props": [ + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "background", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "pageSize", + "defaultValue": 10, + "setters": "NumberSetter" + }, + { + "name": "defaultPageSize", + "label": "默认页大小", + "setters": "NumberSetter" + }, + { + "name": "total", + "title": "总条目数", + "setters": "NumberSetter" + }, + { + "name": "pageCount", + "setters": "NumberSetter" + }, + { + "name": "pagerCount", + "defaultValue": 7, + "setters": "NumberSetter" + }, + { + "name": "currentPage", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "defaultCurrentPage", + "label": "默认当前页", + "setters": "NumberSetter" + }, + { + "name": "layout", + "defaultValue": "prev, pager, next, jumper, ->, total", + "setters": "InputSetter" + }, + { + "name": "pageSizes", + "defaultValue": [10, 20, 30, 40, 50, 100], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "appendSizeTo", + "title": "下拉框挂载到哪个 DOM 元素", + "setters": "StringSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "prevText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "prevIcon", + "defaultValue": "ArrowLeft", + "setters": "InputSetter" + }, + { + "name": "nextText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "nextIcon", + "defaultValue": "ArrowRight", + "setters": "InputSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "teleported ", + "title": "是否将下拉菜单teleport至 body", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "hideOnSinglePage", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "small", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": [ + "size-change", + "current-change", + "change", + "prev-click", + "next-click", + "update:pageSize", + "update:currentPage" + ], + "slots": ["default", "prevIcon", "nextIcon"], + "snippet": { + "props": { + "total": 1000, + "background": true + } + } + }, + "ElPopconfirm": { + "name": "ElPopconfirm", + "label": "气泡确认框", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/popconfirm.html", + "package": "element-plus", + "props": [ + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "confirmButtonText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "cancelButtonText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "confirmButtonType", + "defaultValue": "primary", + "setters": "SelectSetter", + "options": ["primary", "success", "warning", "danger", "info", "text"] + }, + { + "name": "confirmButtonType", + "defaultValue": "text", + "setters": "SelectSetter", + "options": ["primary", "success", "warning", "danger", "info", "text"] + }, + { + "name": "icon", + "defaultValue": "QuestionFilled", + "setters": ["InputSetter"] + }, + { + "name": "iconColor", + "defaultValue": "#f90", + "setters": "ColorSetter" + }, + { + "name": "hideIcon", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "hideAfter", + "defaultValue": 200, + "setters": "NumberSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "persistent", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "width", + "defaultValue": "150", + "setters": ["NumberSetter", "InputSetter"] + } + ], + "events": [ + { + "name": "confirm" + }, + { + "name": "cancel" + } + ], + "slots": [ + { + "name": "reference" + }, + { + "name": "actions" + } + ], + "snippet": { + "name": "ElPopconfirm", + "children": [ + { + "name": "ElButton", + "children": "气泡确认框", + "slot": "reference" + } + ], + "props": { + "title": "标题内容" + } + } + }, + "ElPopover": { + "name": "ElPopover", + "label": "气泡卡片", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/popover.html", + "package": "element-plus", + "props": [ + { + "name": "trigger", + "defaultValue": "primary", + "setters": "click", + "options": ["click", "focus", "hover", "contextmenu"] + }, + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "content", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "width", + "defaultValue": 150, + "setters": ["NumberSetter", "InputSetter"] + }, + { + "name": "placement", + "defaultValue": "bottom", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "visible", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "transition", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "showArrow", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "popperOptions", + "setters": "JSONSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "popperStyle", + "setters": ["InputSetter", "ObjectSetter"] + }, + { + "name": "showAfter", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "hideAfter", + "defaultValue": 200, + "setters": "NumberSetter" + }, + { + "name": "autoClose", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "persistent", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "events": [ + { + "name": "show" + }, + { + "name": "before-enter" + }, + { + "name": "after-enter" + }, + { + "name": "hide" + }, + { + "name": "before-leave" + }, + { + "name": "after-leave" + }, + { + "name": "update:visible" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "reference" + } + ], + "snippet": { + "name": "ElPopover", + "props": { + "placement": "bottom", + "title": "Title", + "width": "200", + "trigger": "hover", + "content": "这是content123!" + }, + "children": [ + { + "name": "ElButton", + "children": "气泡卡片", + "slot": "reference" + } + ] + } + }, + "ElProgress": { + "name": "ElProgress", + "label": "进度条", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/progress.html", + "package": "element-plus", + "props": [ + { + "name": "percentage", + "defaultValue": 0, + "title": "百分比,必填", + "setters": { + "name": "NumberSetter", + "props": { + "min": 0, + "max": 100 + } + } + }, + { + "name": "type", + "defaultValue": "line", + "options": ["line", "circle", "dashboard"], + "setters": "SelectSetter" + }, + { + "name": "strokeWidth", + "defaultValue": 6, + "setters": "NumberSetter" + }, + { + "name": "textInside", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "status", + "defaultValue": "", + "options": ["success", "exception", "warning"], + "setters": "SelectSetter" + }, + { + "name": "indeterminate", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "duration", + "defaultValue": 3, + "setters": "NumberSetter" + }, + { + "name": "color", + "defaultValue": "", + "setters": ["ColorSetter", "FunctionSetter", "ArraySetter", "JSONSetter"] + }, + { + "name": "width", + "defaultValue": 126, + "setters": "NumberSetter" + }, + { + "name": "showText", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "strokeLinecap", + "defaultValue": "round", + "options": ["butt", "round", "square"], + "setters": "SelectSetter" + }, + { + "name": "format", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "striped", + "label": "striped", + "title": "在进度条上增加条纹", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "stripedFlow", + "label": "stripedFlow", + "title": "让进度条上的条纹流动起来", + "setters": "BooleanSetter", + "defaultValue": false + } + ], + "slots": ["default"], + "snippet": { + "name": "ElProgress", + "props": { + "percentage": 50 + } + } + }, + "ElRadio": { + "name": "ElRadio", + "label": "单选框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/radio.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "value", + "title": "单选框的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "label", + "defaultValue": "", + "title": "单选框的 label 如果value没有值, label则作为value使用", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "disabled", + "title": "是否禁用单选框", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "border", + "title": "是否显示边框", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "title": "单选框的尺寸", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "name", + "title": "原始 name 属性", + "defaultValue": "", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "update:modelValue" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "label": "选项一", + "value": "1" + } + } + }, + "ElRadioGroup": { + "name": "ElRadioGroup", + "label": "单选框组", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "绑定值", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "size", + "title": "单选框按钮或边框按钮的大小", + "defaultValue": "", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "textColor", + "title": "按钮形式的 Radio 激活时的文本颜色", + "defaultValue": "#ffffff", + "setters": "ColorSetter" + }, + { + "name": "fill", + "title": "按钮形式的 Radio 激活时的填充色和边框色", + "defaultValue": "#409EFF", + "setters": "ColorSetter" + }, + { + "name": "validateEvent", + "title": "输入时是否触发表单的校验", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "aria-label", + "title": "与 RadioGroup 中的 aria-label 属性相同", + "setters": "StringSetter" + }, + { + "name": "name", + "label": "name", + "title": "原生 name 属性", + "setters": "StringSetter" + }, + { + "name": "id", + "label": "id", + "title": "原生 id 属性", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "update:modelValue" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElRadioGroup", + "children": [ + { + "name": "ElRadio", + "props": { + "label": "选项一", + "value": "1" + } + }, + { + "name": "ElRadio", + "props": { + "label": "选项二", + "value": "2" + } + }, + { + "name": "ElRadio", + "props": { + "label": "选项三", + "value": "3" + } + } + ] + } + }, + "ElRadioButton": { + "name": "ElRadioButton", + "label": "单选框按钮", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "label", + "title": "单选框的label,如果没有value,label则作为value使用", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "value", + "title": "单选框的值", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "disabled", + "title": "是否禁用单选框", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "name", + "title": "原生 name 属性", + "defaultValue": "", + "setters": "StringSetter" + } + ], + "slots": ["default"], + "snippet": { + "children": "按钮选项" + } + }, + "ElRate": { + "name": "ElRate", + "label": "评分", + "childIncludes": false, + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/rate.html", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "max", + "defaultValue": 5, + "setters": "NumberSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowHalf", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "lowThreshold", + "defaultValue": 2, + "title": "低分和中等分数的界限值, 值本身被划分在低分中", + "setters": "NumberSetter" + }, + { + "name": "highThreshold", + "defaultValue": 4, + "title": "高分和中等分数的界限值, 值本身被划分在高分中", + "setters": "NumberSetter" + }, + { + "name": "colors", + "defaultValue": ["#F7BA2A", "#F7BA2A", "#F7BA2A"], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "voidColor", + "defaultValue": "#C6D1DE", + "setters": "ColorSetter" + }, + { + "name": "disabledVoidColor", + "defaultValue": "#EFF2F7", + "label": "disabledColor", + "setters": "ColorSetter" + }, + { + "name": "icons", + "defaultValue": ["StarFilled", "StarFilled", "StarFilled"], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "voidIcon", + "defaultValue": "Star", + "setters": "InputSetter" + }, + { + "name": "disabledVoidIcon", + "defaultValue": "StarFilled", + "label": "disabledIcon", + "setters": "InputSetter" + }, + { + "name": "showText", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "showScore", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "textColor", + "defaultValue": "#1F2D3D", + "setters": "ColorSetter" + }, + { + "name": "texts", + "defaultValue": ["Extremely bad", "Disappointed", "Fair", "Satisfied", "Surprise"], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "scoreTemplate", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "clearable", + "label": "clearable", + "title": "是否可以重置值为 0", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "id", + "label": "id", + "title": "原生 id 属性", + "setters": "StringSetter" + }, + { + "name": "ariaLabel", + "title": "和 Rate 的 aria-label 属性保持一致", + "setters": "StringSetter" + }, + { + "name": "label", + "label": "label", + "title": "和 Rate 的 aria-label 属性保持一致", + "setters": "StringSetter" + } + ], + "events": ["change", "update:modelValue"] + }, + "ElResult": { + "name": "ElResult", + "label": "结果", + "doc": "https://element-plus.org/zh-CN/component/result.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "subTitle", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "icon", + "defaultValue": "info", + "options": ["success", "warning", "info", "error"], + "setters": "SelectSetter" + } + ], + "slots": ["icon", "title", "sub-title", "extra"], + "snippet": { + "props": { + "icon": "success", + "title": "Success Tip", + "subTitle": "Please follow the instructions" + } + } + }, + "ElScrollbar": { + "name": "ElScrollbar", + "label": "滚动条", + "categoryId": "base", + "doc": "https://element-plus.org/zh-CN/component/scrollbar.html", + "childIncludes": false, + "package": "element-plus", + "props": [ + { + "name": "height", + "defaultValue": "", + "setters": ["NumberSetter", "InputSetter"] + }, + { + "name": "maxHeight", + "defaultValue": "", + "setters": ["NumberSetter", "InputSetter"] + }, + { + "name": "native", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "wrapStyle", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "wrapClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "viewStyle", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "viewClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "noresize", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "tag", + "defaultValue": "div", + "setters": "InputSetter" + }, + { + "name": "always", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "minSize", + "defaultValue": 20, + "setters": "NumberSetter" + }, + { + "name": "id", + "label": "id", + "title": "视图id", + "setters": "StringSetter" + }, + { + "name": "role", + "label": "role", + "title": "视图的角色", + "setters": "StringSetter" + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "视图的 aria-label", + "setters": "StringSetter" + }, + { + "name": "ariaOrientation", + "label": "ariaOrientation", + "title": "视图的 aria-orientation", + "setters": "SelectSetter", + "options": ["horizontal", "vertical"] + } + ], + "events": [ + { + "name": "scroll" + } + ], + "snippet": { + "props": { + "style": { + "height": "300px" + } + }, + "children": [ + { + "name": "component", + "props": { + "style": { + "height": "50px", + "margin": "10px", + "background": "#ecf5ff" + } + }, + "directives": [ + { + "name": "vFor", + "value": { + "type": "JSExpression", + "value": "6" + } + } + ] + } + ] + } + }, + "ElSelect": { + "name": "ElSelect", + "label": "选择器", + "doc": "https://element-plus.org/zh-CN/component/select.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["NumberSetter", "InputSetter", "BooleanSetter"] + }, + { + "name": "multiple", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "valueKey", + "defaultValue": "value", + "setters": "InputSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTags", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTagsTooltip", + "title": "当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。 要使用此属性,collapse-tags属性必须设定为 true", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "multipleLimit", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "placeholder", + "defaultValue": "Select", + "setters": "InputSetter" + }, + { + "name": "filterable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowCreate", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remote", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "remoteMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remoteShowSuffix", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loadingText", + "defaultValue": "Loading", + "setters": "InputSetter" + }, + { + "name": "noMatchText", + "defaultValue": "No matching data", + "setters": "InputSetter" + }, + { + "name": "noDataText", + "defaultValue": "No data", + "setters": "InputSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "reserveKeyword", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "defaultFirstOption", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "appendTo", + "title": "下拉框挂载到哪个 DOM 元素", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "persistent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "automaticDropdown", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "setters": "InputSetter" + }, + { + "name": "fitInputWidth", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "suffixIcon", + "defaultValue": "ArrowUp", + "setters": "InputSetter" + }, + { + "name": "tagType", + "defaultValue": "info", + "options": ["success", "info", "warning", "danger"], + "setters": "SelectSetter" + }, + { + "name": "tagEffect", + "defaultValue": "light", + "options": ["", "light", "dark", "plain"], + "setters": "SelectSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "defaultValue": 12, + "setters": "NumberSetter" + }, + { + "name": "showArrow", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "label": "placement", + "title": "下拉框出现的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom-start" + }, + { + "name": "fallbackPlacements", + "label": "fallbackPlacements", + "title": "dropdown 可用的 positions", + "setters": "ArraySetter", + "defaultValue": ["bottom-start", "top-start", "right", "left"] + }, + { + "name": "maxCollapseTags", + "label": "maxCollapseTags", + "title": "需要显示的 Tag 的最大数量 只有当 collapse-tags 设置为 true 时才会生效。", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "popperOptions", + "label": "popperOptions", + "title": "popper.js 参数", + "setters": "ObjectSetter", + "defaultValue": {} + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "等价于原生 input aria-label 属性", + "setters": "StringSetter" + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值 ", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "suffixTransition", + "title": "下拉菜单显示/消失时后缀图标的动画", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "title": "input 的 tabindex", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "events": [ + "change", + "visible-change", + "remove-tag", + "clear", + "blur", + "focus", + "update:modelValue" + ], + "slots": [ + { + "name": "default" + }, + { + "name": "header" + }, + { + "name": "footer" + }, + { + "name": "prefix" + }, + { + "name": "empty" + }, + { + "name": "tag" + }, + { + "name": "loading" + }, + { + "name": "label" + } + ], + "snippet": { + "children": [ + { + "name": "ElOption", + "props": { + "label": { + "type": "JSExpression", + "value": "`选项${this.context.item}`" + } + }, + "directives": [ + { + "name": "vFor", + "value": { + "type": "JSExpression", + "value": "6" + } + } + ] + } + ] + } + }, + "ElOptionGroup": { + "name": "ElOptionGroup", + "label": "选择器选项组", + "categoryId": "form", + "package": "element-plus", + "parentIncludes": ["ElSelect"], + "props": [ + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "label": "分组" + } + } + }, + "ElOption": { + "name": "ElOption", + "label": "选择器选项", + "categoryId": "form", + "package": "element-plus", + "parentIncludes": ["ElSelect", "ElOptionGroup"], + "props": [ + { + "name": "value", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter", "JSONSetter"] + }, + { + "name": "label", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "label": "选项" + } + } + }, + "ElSelectV2": { + "name": "ElSelectV2", + "label": "虚拟列表选择器", + "doc": "https://element-plus.org/zh-CN/component/select-v2.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter", "BooleanSetter", "JSONSetter"] + }, + { + "name": "options", + "label": "options", + "title": "选项的数据源, value 的 key 和 label 可以通过 props自定义.", + "setters": "ArraySetter" + }, + { + "name": "props", + "label": "props", + "title": "配置选项,具体看下表", + "setters": "ObjectSetter" + }, + { + "name": "multiple", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "valueKey", + "defaultValue": "value", + "setters": "InputSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["", "large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "clearIcon", + "label": "clearIcon", + "title": "自定义清除图标", + "setters": ["StringSetter", "ObjectSetter"], + "defaultValue": "CircleClose" + }, + { + "name": "collapseTags", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "multipleLimit", + "label": "multipleLimit", + "title": "多选时可被选择的最大数目。 当被设置为0时,可被选择的数目不设限。", + "setters": "NumberSetter", + "defaultValue": 0 + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": ["SelectSetter", "StringSetter"] + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "placeholder", + "defaultValue": "Please select", + "setters": "InputSetter" + }, + { + "name": "filterable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowCreate", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterMethod", + "label": "filterMethod", + "title": "自定义筛选方法", + "setters": "FunctionSetter" + }, + { + "name": "loading", + "label": "loading", + "title": "是否从远程加载数据", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "loadingText", + "label": "loadingText", + "title": "从服务器加载数据时显示的文本,默认为“Loading”", + "setters": "StringSetter", + "defaultValue": "Loading" + }, + { + "name": "reserveKeyword", + "label": "reserveKeyword", + "title": "筛选时,是否在选择选项后保留关键字", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "noMatchText", + "label": "noMatchText", + "title": "搜索条件无匹配时显示的文字,也可以使用 empty 插槽设置,默认是 “No matching data“", + "setters": "StringSetter" + }, + { + "name": "noDataText", + "label": "noDataText", + "title": "当在没有数据时显示的文字,你同时可以使用empty插槽进行设置。", + "setters": "StringSetter", + "defaultValue": "No Data" + }, + { + "name": "popperClass", + "label": "popperClass", + "title": "选择器下拉菜单的自定义类名", + "setters": "StringSetter", + "defaultValue": "" + }, + { + "name": "teleported", + "label": "teleported", + "title": "是否将下拉列表元素插入 append-to 指向的元素下", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "appendTo", + "title": "下拉框挂载到哪个 DOM 元素", + "setters": "StringSetter" + }, + { + "name": "persistent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "popperOptions", + "label": "popperOptions", + "setters": "ObjectSetter", + "defaultValue": {} + }, + { + "name": "automaticDropdown", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "fitInputWidth", + "defaultValue": true, + "setters": ["BooleanSetter", "NumberSetter"] + }, + { + "name": "height", + "defaultValue": 274, + "setters": "NumberSetter" + }, + { + "name": "itemHeight", + "label": "itemHeight", + "title": "下拉项的高度", + "setters": "NumberSetter", + "defaultValue": 34 + }, + { + "name": "scrollbarAlwaysOn", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "remote", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "remoteMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "title": "下拉面板偏移量", + "defaultValue": 12, + "setters": "NumberSetter" + }, + { + "name": "showArrow", + "title": "下拉菜单的内容是否有箭头", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "label": "placement", + "title": "下拉框出现的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom-start" + }, + { + "name": "fallbackPlacements", + "setters": "ArraySetter", + "defaultValue": ["bottom-start", "top-start", "right", "left"] + }, + { + "name": "collapseTagsTooltip", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "maxCollapseTags", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "tagType", + "label": "tagType", + "title": "标签类型", + "setters": "SelectSetter", + "options": ["", "success", "info", "warning", "danger"], + "defaultValue": "info" + }, + { + "name": "tagEffect", + "title": "标签效果", + "defaultValue": "light", + "options": ["", "light", "dark", "plain"], + "setters": "SelectSetter" + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "等价于原生 input aria-label 属性", + "setters": "StringSetter" + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值 ", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "popperAppendToBody", + "title": "是否将弹出框插入至 body 元素 当弹出框的位置出现问题时,你可以尝试将该属性设置为false。", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "tabindex", + "title": "input 的 tabindex", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "events": [ + "change", + "visible-change", + "remove-tag", + "clear", + "blur", + "focus", + "update:modelValue" + ], + "slots": [ + { + "name": "default", + "params": ["item"] + }, + { + "name": "header" + }, + { + "name": "footer" + }, + { + "name": "prefix" + }, + { + "name": "empty" + }, + { + "name": "tag" + }, + { + "name": "loading" + }, + { + "name": "label" + } + ] + }, + "ElSkeleton": { + "name": "ElSkeleton", + "label": "骨架屏", + "doc": "https://element-plus.org/zh-CN/component/skeleton.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "animated", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "count", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "rows", + "defaultValue": 3, + "setters": "NumberSetter" + }, + { + "name": "throttle", + "defaultValue": 0, + "setters": ["NumberSetter", "ObjectSetter"] + } + ], + "slots": [ + { + "name": "default", + "params": ["object"] + }, + { + "name": "template", + "params": ["object"] + } + ] + }, + "ElSkeletonItem": { + "name": "ElSkeletonItem", + "label": "骨架项", + "doc": "https://element-plus.org/zh-CN/component/skeleton.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "variant", + "setters": "SelectSetter", + "options": ["p", "text", "h1", "h3", "caption", "button", "image", "circle", "rect"], + "defaultValue": "text" + } + ], + "snippet": { + "props": { + "variant": "image", + "style": { + "width": "240px", + "height": "240px" + } + } + } + }, + "ElSlider": { + "name": "ElSlider", + "label": "滑块", + "childIncludes": false, + "doc": "https://element-plus.org/zh-CN/component/slider.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "选中项绑定值", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "min", + "title": "最小值", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "max", + "title": "最大值", + "defaultValue": 100, + "setters": "NumberSetter" + }, + { + "name": "disabled", + "title": "是否禁用", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "step", + "title": "步长", + "defaultValue": 1, + "setters": "NumberSetter" + }, + { + "name": "showInput", + "title": "是否显示输入框,仅在非范围选择时有效", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "showInputControls", + "title": "在显示输入框的情况下,是否显示输入框的控制按钮", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "title": "slider 包装器的大小,垂直模式下该属性不可用", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "inputSize", + "title": "输入框的大小,如果设置了 size 属性,默认值自动取 size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "showStops", + "defaultValue": false, + "title": "是否显示间断点", + "setters": "BooleanSetter" + }, + { + "name": "showTooltip", + "defaultValue": true, + "title": "是否显示提示信息", + "setters": "BooleanSetter" + }, + { + "name": "formatTooltip", + "title": "格式化提示信息", + "setters": "FunctionSetter" + }, + { + "name": "range", + "title": "是否开启选择范围", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "vertical", + "defaultValue": false, + "title": "垂直模式", + "setters": "BooleanSetter" + }, + { + "name": "height", + "defaultValue": "", + "title": "滑块高度,垂直模式必填", + "setters": "InputSetter" + }, + { + "name": "aria-label", + "title": "原生 aria-label属性", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rangeStartLabel", + "defaultValue": "", + "title": "当 range 为true时,屏幕阅读器标签开始的标记", + "setters": "InputSetter" + }, + { + "name": "rangeEndLabel", + "defaultValue": "", + "title": "当 range 为true时,屏幕阅读器标签结尾的标记", + "setters": "InputSetter" + }, + { + "name": "formatValueText", + "title": "显示屏幕阅读器的 aria-valuenow 属性的格式", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "debounce", + "defaultValue": 300, + "title": "输入时的去抖延迟,毫秒,仅在 show-input 等于 true 时有效", + "setters": "NumberSetter" + }, + { + "name": "tooltipClass", + "title": "tooltip 的自定义类名", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "placement", + "title": "Tooltip 出现的位置", + "defaultValue": "top", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "setters": "SelectSetter" + }, + { + "name": "marks", + "title": "标记, key 的类型必须为 number 且取值在闭区间 [min, max] 内,每个标记可以单独设置样式", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "validateEvent", + "title": "输入时是否触发表单的校验", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "events": ["change", "input", "update:modelValue"] + }, + "ElSpace": { + "name": "ElSpace", + "label": "间距", + "categoryId": "base", + "doc": "https://element-plus.org/zh-CN/component/space.html", + "package": "element-plus", + "props": [ + { + "name": "alignment", + "defaultValue": "center", + "title": "对齐的方式", + "options": [ + "normal", + "stretch", + "center", + "start", + "end", + "flex-start", + "flex-end", + "baseline", + "first baseline", + "last baseline", + "safe center", + "unsafe center", + "inherit", + "initial", + "revert", + "revert-layer", + "unset" + ], + "setters": "SelectSetter" + }, + { + "name": "class", + "title": "className", + "defaultValue": "", + "setters": ["StringSetter", "ObjectSetter", "ArraySetter"] + }, + { + "name": "direction", + "title": "排列的方向", + "defaultValue": "horizontal", + "options": ["vertical", "horizontal"], + "setters": "SelectSetter" + }, + { + "name": "prefixCls", + "title": "给 space-items 的类名前缀", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "style", + "title": "额外样式", + "defaultValue": "", + "setters": ["StringSetter", "JSONSetter"] + }, + { + "name": "spacer", + "title": "间隔符", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "size", + "title": "间隔大小", + "defaultValue": "small", + "setters": ["SelectSetter", "NumberSetter", "ArraySetter"], + "options": ["large", "default", "small"] + }, + { + "name": "wrap", + "title": "设置是否自动折行", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "fill", + "title": "子元素是否填充父容器", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "fillRatio", + "title": "填充父容器的比例", + "defaultValue": 100, + "setters": "NumberSetter" + } + ], + "slots": ["default", "spacer"], + "snippet": { + "props": { + "fill": true, + "style": { + "width": "100%" + } + }, + "children": [ + { + "name": "ElCard" + }, + { + "name": "ElCard" + } + ] + } + }, + "ElStatistic": { + "name": "ElStatistic", + "label": "统计组件", + "doc": "https://element-plus.org/zh-CN/component/statistic.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "value", + "label": "value", + "title": "数字内容", + "setters": "NumberSetter", + "defaultValue": 0 + }, + { + "name": "decimalSeparator", + "label": "decimalSeparator", + "title": "设置小数点符号", + "setters": "StringSetter", + "defaultValue": "." + }, + { + "name": "formatter", + "label": "formatter", + "title": "自定义数字格式化", + "setters": "FunctionSetter" + }, + { + "name": "groupSeparator", + "label": "groupSeparator", + "title": "设置千分位标识符", + "setters": "StringSetter", + "defaultValue": "," + }, + { + "name": "precision", + "label": "precision", + "title": "数字精度", + "setters": "NumberSetter", + "defaultValue": 0 + }, + { + "name": "prefix", + "label": "prefix", + "title": "设置数字的前缀", + "setters": "StringSetter" + }, + { + "name": "suffix", + "label": "suffix", + "title": "设置数字的后缀", + "setters": "StringSetter" + }, + { + "name": "title", + "label": "title", + "title": "数字标题", + "setters": "StringSetter" + }, + { + "name": "valueStyle", + "label": "valueStyle", + "title": "数字样式", + "setters": ["StringSetter", "ObjectSetter", "ArraySetter"] + } + ], + "slots": ["prefix", "suffix", "title"], + "snippet": { + "props": { + "title": "Daily active users", + "value": "268500" + } + } + }, + "ElCountdown": { + "name": "ElCountdown", + "label": "倒计时", + "doc": "https://element-plus.org/zh-CN/component/statistic.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "value", + "label": "value", + "title": "目标时间", + "setters": ["NumberSetter"] + }, + { + "name": "format", + "label": "format", + "title": "格式化倒计时", + "setters": "StringSetter", + "defaultValue": "HH:mm:ss" + }, + { + "name": "prefix", + "label": "prefix", + "title": "设置倒计时前缀", + "setters": "StringSetter" + }, + { + "name": "suffix", + "label": "suffix", + "title": "设置倒计时的后缀", + "setters": "StringSetter" + }, + { + "name": "title", + "label": "title", + "title": "倒计时标题", + "setters": "StringSetter" + }, + { + "name": "valueStyle", + "label": "valueStyle", + "title": "倒计时值的样式", + "setters": ["StringSetter", "ObjectSetter", "ArraySetter"] + } + ], + "events": ["change", "finish"], + "slots": ["prefix", "suffix", "title"], + "snippet": { + "props": { + "title": "Start to grab", + "value": 1792134444342 + } + } + }, + "ElSegmented": { + "name": "ElSegmented", + "label": "分段控制器", + "doc": "https://element-plus.org/zh-CN/component/segmented.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "title": "绑定值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter"] + }, + { + "name": "options", + "title": "选项的数据", + "defaultValue": [], + "setters": "ArraySetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["", "large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "validate-event", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "name", + "setters": "StringSetter" + }, + { + "name": "id", + "setters": "StringSetter" + }, + { + "name": "ariaLabel", + "setters": "StringSetter" + }, + { + "name": "direction", + "defaultValue": "horizontal", + "options": ["horizontal", "vertical"], + "setters": "SelectSetter" + } + ], + "events": ["change", "update:modelValue"], + "slots": ["default"], + "snippet": { + "props": { + "modelValue": "Mom", + "options": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + } + } + }, + "ElSteps": { + "name": "ElSteps", + "label": "步骤条", + "categoryId": "nav", + "doc": "https://element-plus.org/zh-CN/component/steps.html", + "package": "element-plus", + "props": [ + { + "name": "space", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "direction", + "defaultValue": "horizontal", + "setters": "SelectSetter", + "options": ["vertical", "horizontal"] + }, + { + "name": "active", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "processStatus", + "defaultValue": "process", + "setters": "SelectSetter", + "options": ["wait", "process", "finish", "error", "success"] + }, + { + "name": "finishStatus", + "defaultValue": "finish", + "setters": "SelectSetter", + "options": ["wait", "process", "finish", "error", "success"] + }, + { + "name": "alignCenter", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "simple", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "slots": ["default"], + "snippet": { + "name": "ElSteps", + "children": [ + { + "name": "ElStep", + "props": { + "title": "Step 1" + } + }, + { + "name": "ElStep", + "props": { + "title": "Step 2" + } + }, + { + "name": "ElStep", + "props": { + "title": "Step 3" + } + } + ], + "props": { + "active": 0, + "finishStatus": "success" + } + } + }, + "ElStep": { + "name": "ElStep", + "label": "步骤项", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "title", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "description", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "icon", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "status", + "defaultValue": "", + "setters": "SelectSetter", + "options": ["wait", "process", "finish", "error", "success"] + } + ], + "slots": [ + { + "name": "icon" + }, + { + "name": "title" + }, + { + "name": "description" + } + ], + "snippet": { + "props": { + "title": "步骤" + } + } + }, + "ElSwitch": { + "name": "ElSwitch", + "label": "开关", + "childIncludes": false, + "doc": "https://element-plus.org/zh-CN/component/switch.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": false, + "setters": ["BooleanSetter", "NumberSetter", "InputSetter"] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "width", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "inlinePrompt", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "activeIcon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "inactiveIcon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "activeActionIcon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "inactiveActionIcon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "activeText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "inactiveText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "activeValue", + "defaultValue": true, + "setters": ["BooleanSetter", "InputSetter", "NumberSetter"] + }, + { + "name": "inactiveValue", + "defaultValue": false, + "setters": ["BooleanSetter", "InputSetter", "NumberSetter"] + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "beforeChange", + "setters": ["BooleanSetter", "FunctionSetter"] + }, + { + "name": "id", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "tabindex", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "ariaLabel", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "activeColor", + "defaultValue": "", + "setters": "ColorSetter" + }, + { + "name": "inactiveColor", + "defaultValue": "", + "setters": "ColorSetter" + }, + { + "name": "borderColor", + "defaultValue": "", + "setters": "ColorSetter" + }, + { + "name": "label", + "defaultValue": "", + "setters": "StringSetter" + } + ], + "events": ["change", "update:modelValue"], + "slots": ["active-action", "inactive-action"] + }, + "ElTable": { + "name": "ElTable", + "label": "表格", + "doc": "https://element-plus.org/zh-CN/component/table.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "data", + "defaultValue": "", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "height", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "maxHeight", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "stripe", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "border", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "", + "options": ["", "large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "fit", + "defaultValue": true, + "title": "列的宽度是否自撑开", + "setters": "BooleanSetter" + }, + { + "name": "showHeader", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "highlightCurrentRow", + "defaultValue": false, + "label": "是否高亮", + "setters": "BooleanSetter" + }, + { + "name": "currentRowKey", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "rowClassName", + "defaultValue": "", + "setters": ["InputSetter", "FunctionSetter"] + }, + { + "name": "rowStyle", + "defaultValue": "", + "setters": ["JSONSetter", "FunctionSetter"] + }, + { + "name": "cellClassName", + "defaultValue": "", + "setters": ["InputSetter", "FunctionSetter"] + }, + { + "name": "cellStyle", + "defaultValue": "", + "setters": ["JSONSetter", "FunctionSetter"] + }, + { + "name": "headerRowClassName", + "defaultValue": "", + "title": "表头行类名", + "label": "RowClassName", + "setters": ["InputSetter", "FunctionSetter"] + }, + { + "name": "headerRowStyle", + "defaultValue": "", + "setters": ["JSONSetter", "FunctionSetter"] + }, + { + "name": "headerCellClassName", + "defaultValue": "", + "title": "表头单元格类名", + "label": "CellClassName", + "setters": ["InputSetter", "FunctionSetter"] + }, + { + "name": "headerCellStyle", + "defaultValue": "", + "setters": ["JSONSetter", "FunctionSetter"] + }, + { + "name": "rowKey", + "defaultValue": "", + "setters": ["InputSetter", "FunctionSetter"] + }, + { + "name": "emptyText", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "defaultExpandAll", + "defaultValue": false, + "label": "展开所有", + "setters": "BooleanSetter" + }, + { + "name": "expand-row-keys", + "defaultValue": "", + "title": "可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。", + "label": "row-keys", + "setters": "JSONSetter" + }, + { + "name": "default-sort", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "tooltip-effect", + "defaultValue": "dark", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "tooltip-options", + "defaultValue": { + "enterable": true, + "placement": "top", + "showArrow": true, + "hideAfter": 200, + "popperOptions": { + "strategy": "fixed" + } + }, + "setters": "ObjectSetter" + }, + { + "name": "show-summary", + "defaultValue": false, + "label": "显示合计行", + "setters": "BooleanSetter" + }, + { + "name": "sum-text", + "defaultValue": "合计", + "setters": "InputSetter" + }, + { + "name": "summary-method", + "defaultValue": "", + "label": "合计计算方法", + "setters": "FunctionSetter" + }, + { + "name": "span-method", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "select-on-indeterminate", + "defaultValue": true, + "title": "在多选表格中,当仅有部分行被选中时,点击表头的多选框时的行为。 若为 true,则选中所有行;若为 false,则取消选择所有行", + "label": "indeterminate", + "setters": "BooleanSetter" + }, + { + "name": "indent", + "defaultValue": 16, + "setters": "NumberSetter" + }, + { + "name": "lazy", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "load", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "tree-props", + "defaultValue": { + "hasChildren": "hasChildren", + "children": "children" + }, + "setters": "JSONSetter" + }, + { + "name": "tableLayout", + "defaultValue": "fixed", + "title": "设置表格单元、行和列的布局方式", + "options": ["fixed", "auto"], + "setters": "SelectSetter" + }, + { + "name": "scrollbar-always-on", + "defaultValue": false, + "label": "显示滚动条", + "setters": "BooleanSetter" + }, + { + "name": "show-overflow-tooltip", + "setters": ["BooleanSetter", "JSONSetter"] + }, + { + "name": "flexible", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "scrollbarTabindex", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "allowDragLastColumn", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "events": [ + "select", + "select-all", + "selection-change", + "cell-mouse-enter", + "cell-mouse-leave", + "cell-click", + "cell-dblclick", + "cell-contextmenu", + "row-click", + "row-contextmenu", + "row-dblclick", + "header-click", + "header-contextmenu", + "sort-change", + "filter-change", + "current-change", + "header-dragend", + "expand-change", + "scroll" + ], + "slots": ["default", "append", "empty"], + "snippet": { + "name": "ElTable", + "props": { + "data": [ + { + "date": "2016-05-03", + "name": "Tom", + "address": "No. 189, Grove St, Los Angeles" + }, + { + "date": "2016-05-02", + "name": "Tom", + "address": "No. 189, Grove St, Los Angeles" + }, + { + "date": "2016-05-04", + "name": "Tom", + "address": "No. 189, Grove St, Los Angeles" + }, + { + "date": "2016-05-01", + "name": "Tom", + "address": "No. 189, Grove St, Los Angeles" + } + ] + }, + "children": [ + { + "name": "ElTableColumn", + "props": { + "prop": "date", + "label": "Date" + } + }, + { + "name": "ElTableColumn", + "props": { + "prop": "name", + "label": "Name" + } + }, + { + "name": "ElTableColumn", + "props": { + "prop": "address", + "label": "Address" + } + } + ] + } + }, + "ElTableColumn": { + "name": "ElTableColumn", + "label": "表头", + "categoryId": "data", + "package": "element-plus", + "parentIncludes": ["ElTable"], + "props": [ + { + "name": "type", + "defaultValue": "default", + "options": ["default", "selection", "index", "expand"], + "setters": "SelectSetter" + }, + { + "name": "index", + "defaultValue": 0, + "title": "如果设置了 type=index,可以通过传递 index 属性来自定义索引", + "setters": ["NumberSetter", "FunctionSetter"] + }, + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "column-key", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "prop", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "width", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "min-width", + "defaultValue": "", + "title": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "fixed", + "defaultValue": "", + "options": ["left", "right"], + "setters": ["SelectSetter", "BooleanSetter"] + }, + { + "name": "render-header", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "sortable", + "defaultValue": false, + "options": ["", "custom"], + "setters": ["BooleanSetter", "SelectSetter"] + }, + { + "name": "sort-method", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "sort-by", + "defaultValue": "", + "setters": ["InputSetter", "FunctionSetter", "JSONSetter"] + }, + { + "name": "sort-orders", + "defaultValue": ["ascending", "descending", null], + "title": "数据在排序时所使用排序策略的轮转顺序,仅当 sortable 为 true 时有效。 需传入一个数组,随着用户点击表头,该列依次按照数组中元素的顺序进行排序", + "setters": "JSONSetter" + }, + { + "name": "resizable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "formatter", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "show-overflow-tooltip", + "title": "当内容过长被隐藏时显示 tooltip", + "setters": ["BooleanSetter", "JSONSetter"] + }, + { + "name": "align", + "defaultValue": "left", + "options": ["left", "center", "right"], + "setters": "SelectSetter" + }, + { + "name": "header-align", + "defaultValue": "left", + "options": ["left", "center", "right"], + "setters": "SelectSetter" + }, + { + "name": "class-name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "label-class-name", + "defaultValue": "", + "title": "当前列标题的自定义类名", + "setters": "InputSetter" + }, + { + "name": "selectable", + "setters": "FunctionSetter" + }, + { + "name": "reserve-selection", + "defaultValue": false, + "title": "仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。", + "setters": "BooleanSetter" + }, + { + "name": "filters", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "filter-placement", + "defaultValue": "", + "title": "过滤弹出框的定位,与 Tooltip 的 placement 属性相同", + "setters": "InputSetter" + }, + { + "name": "filter-class-name", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "filter-multiple", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "filter-method", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "filtered-value", + "defaultValue": "", + "setters": "JSONSetter" + } + ], + "slots": [ + { + "name": "default", + "params": ["row", "column", "$index"] + }, + { + "name": "header", + "params": ["column", "$index"] + }, + { + "name": "filter-icon", + "params": ["filterOpened"] + } + ], + "snippet": { + "props": { + "label": "列名" + } + } + }, + "ElTabs": { + "name": "ElTabs", + "childIncludes": ["ElTabPane"], + "label": "标签页", + "doc": "https://element-plus.org/zh-CN/component/tabs.html", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "type", + "setters": [ + { + "name": "SelectSetter", + "props": { + "closable": true + } + } + ], + "defaultValue": "", + "options": ["", "card", "border-card"] + }, + { + "name": "closable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "addable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "editable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "tabPosition", + "defaultValue": "top", + "setters": "SelectSetter", + "options": ["top", "right", "bottom", "left"] + }, + { + "name": "stretch", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "beforeLeave", + "defaultValue": "", + "setters": "FunctionSetter" + } + ], + "events": [ + { + "name": "tab-click" + }, + { + "name": "tab-change" + }, + { + "name": "tab-remove" + }, + { + "name": "tab-add" + }, + { + "name": "edit" + }, + { + "name": "update:modelValue" + } + ], + "slots": ["default", "addIcon", "add-icon"], + "snippet": { + "props": { + "modelValue": "1" + }, + "children": [ + { + "name": "ElTabPane", + "children": "面板一内容", + "props": { + "label": "面板一", + "name": "1" + } + }, + { + "name": "ElTabPane", + "children": "面板二内容", + "props": { + "label": "面板二", + "name": "2" + } + }, + { + "name": "ElTabPane", + "children": "面板三内容", + "props": { + "label": "面板三", + "name": "3" + } + } + ] + } + }, + "ElTabPane": { + "name": "ElTabPane", + "label": "标签页面板", + "categoryId": "nav", + "package": "element-plus", + "props": [ + { + "name": "label", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "closable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "lazy", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "label" + } + ], + "snippet": { + "props": { + "label": "面板标题" + }, + "children": "面板内容" + } + }, + "ElTag": { + "name": "ElTag", + "label": "标签", + "doc": "https://element-plus.org/zh-CN/component/tag.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "type", + "defaultValue": "primary", + "options": ["primary", "success", "info", "warning", "danger"], + "setters": "SelectSetter" + }, + { + "name": "closable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disable-transitions", + "defaultValue": false, + "label": "渐变动画", + "setters": "BooleanSetter" + }, + { + "name": "hit", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "color", + "defaultValue": "", + "setters": "ColorSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light", "plain"], + "setters": "SelectSetter" + }, + { + "name": "round", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "events": ["click", "close"], + "slots": ["default"], + "snippet": { + "children": "标签一" + } + }, + "ElCheckTag": { + "name": "ElCheckTag", + "label": "可选中的标签", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "checked", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "type", + "label": "type", + "title": "CheckTag 类型", + "setters": "SelectSetter", + "options": ["primary", "success", "info", "warning", "danger"], + "defaultValue": "primary" + } + ], + "events": ["change", "update:checked"], + "slots": ["default"], + "snippet": { + "children": "标签一" + } + }, + "ElText": { + "name": "ElText", + "label": "文本", + "categoryId": "base", + "doc": "https://element-plus.org/zh-CN/component/text.html", + "props": [ + { + "name": "type", + "label": "type", + "title": "类型", + "setters": "SelectSetter", + "options": ["primary", "success", "warning", "danger", "info"] + }, + { + "name": "size", + "label": "size", + "title": "大小", + "setters": "SelectSetter", + "options": ["large", "default", "small"], + "defaultValue": "default" + }, + { + "name": "truncated", + "label": "truncated", + "title": "显示省略号", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "lineClamp", + "label": "lineClamp", + "title": "最大行数", + "setters": ["StringSetter", "NumberSetter"] + }, + { + "name": "tag", + "label": "tag", + "title": "自定义元素标签", + "setters": "StringSetter", + "defaultValue": "span" + } + ], + "slots": ["default"], + "snippet": { + "props": { + "type": "primary" + }, + "children": "这是一段Primary颜色的文本" + }, + "package": "element-plus" + }, + "ElTimeline": { + "name": "ElTimeline", + "label": "时间线", + "doc": "https://element-plus.org/zh-CN/component/timeline.html", + "categoryId": "form", + "package": "element-plus", + "slots": ["default"], + "snippet": { + "name": "ElTimeline", + "children": [ + { + "name": "ElTimelineItem", + "children": "Event start", + "props": { + "timestamp": "2018-04-15", + "size": "large", + "type": "primary", + "icon": "MoreFilled" + } + }, + { + "name": "ElTimelineItem", + "children": "Approved", + "props": { + "timestamp": "2018-04-13", + "color": "#0bbd87" + } + }, + { + "name": "ElTimelineItem", + "children": "Success", + "props": { + "timestamp": "2018-04-11", + "hollow": true, + "icon": "el-icon-more" + } + } + ] + } + }, + "ElTimelineItem": { + "name": "ElTimelineItem", + "label": "时间线子项", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "timestamp", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "hide-timestamp", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "center", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "defaultValue": "bottom", + "options": ["top", "bottom"], + "setters": "SelectSetter" + }, + { + "name": "type", + "defaultValue": "", + "options": ["primary", "success", "warning", "danger", "info"], + "setters": "SelectSetter" + }, + { + "name": "color", + "defaultValue": "", + "options": ["hsl", "hsv", "hex", "rgb"], + "setters": "SelectSetter" + }, + { + "name": "size", + "defaultValue": "normal", + "options": ["normal", "large"], + "setters": "SelectSetter" + }, + { + "name": "icon", + "defaultValue": "", + "setters": "IconSetter" + }, + { + "name": "hollow", + "defaultValue": false, + "setters": "BooleanSetter" + } + ], + "slots": ["default", "dot"] + }, + "ElTimePicker": { + "name": "ElTimePicker", + "label": "时间选择器", + "childIncludes": false, + "doc": "https://element-plus.org/zh-CN/component/time-picker.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["NumberSetter", "StringSetter", "ArraySetter", "ExpressionSetter"] + }, + { + "name": "readonly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "editable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "startPlaceholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "endPlaceholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "isRange", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "arrowControl", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rangeSeparator", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "format", + "defaultValue": "HH:mm:ss", + "setters": "InputSetter" + }, + { + "name": "defaultValue", + "defaultValue": "", + "setters": ["InputSetter", "ExpressionSetter"] + }, + { + "name": "valueFormat", + "title": "可选,绑定值的格式。 不指定则绑定值为 Date 对象", + "defaultValue": "", + "setters": "StringSetter" + }, + { + "name": "id", + "defaultValue": "", + "setters": ["InputSetter"] + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "ariaLabel", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "prefixIcon", + "defaultValue": "Clock", + "setters": "InputSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "setters": "InputSetter" + }, + { + "name": "disabledHours", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "disabledMinutes", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "disabledSeconds", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "label": "tabindex", + "title": "输入框的 tabindex", + "setters": ["StringSetter", "NumberSetter"], + "defaultValue": 0 + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + } + ], + "events": ["change", "blur", "focus", "clear", "visible-change", "update:modelValue"] + }, + "ElTimeSelect": { + "name": "ElTimeSelect", + "label": "时间选择", + "childIncludes": false, + "doc": "https://element-plus.org/zh-CN/component/time-select.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["StringSetter", "ExpressionSetter"] + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "editable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "clearable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "placeholder", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "prefixIcon", + "defaultValue": "Clock", + "setters": "InputSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "setters": "InputSetter" + }, + { + "name": "start", + "defaultValue": "09:00", + "setters": "InputSetter" + }, + { + "name": "end", + "defaultValue": "18:00", + "setters": "InputSetter" + }, + { + "name": "step", + "defaultValue": "00:30", + "setters": "InputSetter" + }, + { + "name": "minTime", + "defaultValue": "00:00", + "setters": "InputSetter" + }, + { + "name": "maxTime", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "format", + "defaultValue": "HH:mm", + "setters": "InputSetter" + }, + { + "name": "emptyValues", + "title": "组件的空值配置", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "title": "清空选项的值", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + } + ], + "events": ["change", "blur", "focus", "clear", "update:modelValue"] + }, + "ElTooltip": { + "name": "ElTooltip", + "childIncludes": true, + "label": "文字提示", + "doc": "https://element-plus.org/zh-CN/component/tooltip.html", + "categoryId": "other", + "package": "element-plus", + "props": [ + { + "name": "appendTo", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "dark", + "setters": "InputSetter" + }, + { + "name": "content", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "rawContent", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "defaultValue": "bottom", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ] + }, + { + "name": "fallback-placements", + "setters": "ArraySetter" + }, + { + "name": "visible", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "transition", + "defaultValue": "el-fade-in-linear", + "setters": "InputSetter" + }, + { + "name": "popperOptions", + "defaultValue": { + "boundariesElement": "body", + "gpuAcceleration": false + }, + "setters": "JSONSetter" + }, + { + "name": "showAfter", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "show-arrow", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "hide-after", + "defaultValue": 200, + "setters": "NumberSetter" + }, + { + "name": "auto-close", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "popper-class", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "enterable", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "teleported", + "label": "teleported", + "title": "是否使用 teleport。设置成 true则会被追加到 append-to 的位置", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "trigger", + "label": "trigger", + "title": "如何触发 Tooltip", + "setters": "SelectSetter", + "options": ["hover", "click", "focus", "contextmenu"], + "defaultValue": "hover" + }, + { + "name": "virtual-triggering", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "virtual-ref", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "trigger-keys", + "defaultValue": ["Enter", "Space"], + "setters": "ExpressionSetter" + }, + { + "name": "persistent", + "setters": "BooleanSetter" + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "和 aria-label 属性保持一致", + "setters": "StringSetter" + } + ], + "events": [ + { + "name": "confirm" + }, + { + "name": "cancel" + }, + { + "name": "update:visible " + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "content" + } + ], + "snippet": { + "name": "ElTooltip", + "children": "文字提示", + "props": { + "content": "自定义弹出框的内容" + } + } + }, + "ElTour": { + "name": "ElTour", + "label": "漫游式引导", + "doc": "https://element-plus.org/zh-CN/component/tour.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "showArrow", + "label": "showArrow", + "title": "是否显示箭头", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "placement", + "label": "placement", + "title": "引导卡片相对于目标元素的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom" + }, + { + "name": "contentStyle", + "label": "contentStyle", + "title": "为content自定义样式", + "setters": "ObjectSetter" + }, + { + "name": "mask", + "label": "mask", + "title": "是否启用遮罩,通过自定义属性改变遮罩样式以及填充的颜色", + "setters": ["BooleanSetter", "ObjectSetter"], + "defaultValue": true + }, + { + "name": "type", + "label": "type", + "title": "类型,影响底色与文字颜色", + "setters": "SelectSetter", + "options": ["default", "primary"], + "defaultValue": "default" + }, + { + "name": "modelValue", + "label": "modelValue", + "title": "打开引导", + "setters": "BooleanSetter", + "defaultValue": false + }, + { + "name": "current", + "label": "current", + "title": "当前值", + "setters": "NumberSetter" + }, + { + "name": "scroll-into-view-options", + "label": "scroll-into-view-options", + "title": "是否支持当前元素滚动到视窗内,也可传入配置指定滚动视窗的相关参数", + "setters": ["BooleanSetter", "ObjectSetter"], + "defaultValue": { + "block": "center" + } + }, + { + "name": "z-index", + "label": "z-index", + "title": "Tour 的层级", + "setters": "NumberSetter", + "defaultValue": 2001 + }, + { + "name": "show-close", + "label": "show-close", + "title": "是否显示关闭按钮", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "close-icon", + "label": "close-icon", + "title": "自定义关闭图标", + "setters": "IconSetter", + "defaultValue": "Close" + }, + { + "name": "close-on-press-escape", + "label": "close-on-press-escape", + "title": "是否可以通过按下 ESC 关闭引导", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "target-area-clickable", + "label": "target-area-clickable", + "title": "启用蒙层时,target 元素区域是否可以点击。", + "setters": "BooleanSetter", + "defaultValue": true + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "indicators", + "params": ["current", "total"] + }, + { + "name": "close-icon" + } + ], + "events": ["close", "finish", "change", "update:modelValue", "update:current"], + "snippet": { + "props": { + "modelValue": true + }, + "children": [ + { + "name": "ElTourStep", + "props": { + "title": "Center", + "description": "Displayed in the center of screen." + } + }, + { + "name": "ElTourStep", + "props": { + "title": "Center", + "description": "Displayed in the center of screen." + } + }, + { + "name": "ElTourStep", + "props": { + "title": "Center", + "description": "Displayed in the center of screen." + } + } + ] + } + }, + "ElTourStep": { + "name": "ElTourStep", + "label": "漫游式引导步", + "parentIncludes": ["ElTour"], + "doc": "https://element-plus.org/zh-CN/component/tour.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "target", + "label": "target", + "title": "获取引导卡片指向的元素, 为空时居中于屏幕。", + "setters": ["StringSetter", "FunctionSetter"] + }, + { + "name": "showArrow", + "label": "showArrow", + "title": "是否显示箭头", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "title", + "label": "title", + "title": "标题", + "setters": "StringSetter" + }, + { + "name": "description", + "label": "description", + "title": "主要描述部分", + "setters": "StringSetter" + }, + { + "name": "placement", + "label": "placement", + "title": "引导卡片相对于目标元素的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom" + }, + { + "name": "contentStyle", + "label": "contentStyle", + "title": "为content自定义样式", + "setters": "ObjectSetter" + }, + { + "name": "mask", + "label": "mask", + "title": "是否启用蒙层,也可传入配置改变蒙层样式和填充色", + "setters": ["BooleanSetter", "ObjectSetter"], + "defaultValue": true + }, + { + "name": "type", + "label": "type", + "title": "类型,影响底色与文字颜色", + "setters": "SelectSetter", + "options": ["default", "primary"], + "defaultValue": "default" + }, + { + "name": "nextButtonProps", + "label": "nextButtonProps", + "title": "“下一步”按钮的属性", + "setters": "ObjectSetter" + }, + { + "name": "prev-button-props", + "label": "prev-button-props", + "title": "“上一步”按钮的属性", + "setters": "ObjectSetter" + }, + { + "name": "scrollIntoViewOptions", + "label": "scrollIntoViewOptions", + "title": "是否支持当前元素滚动到视窗内,也可传入配置指定滚动视窗的相关参数", + "setters": ["BooleanSetter", "ObjectSetter"] + }, + { + "name": "showClose", + "label": "showClose", + "title": "是否显示关闭按钮", + "setters": "BooleanSetter", + "defaultValue": true + }, + { + "name": "closeIcon", + "label": "closeIcon", + "title": "自定义关闭图标", + "setters": ["IconSetter"] + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "header" + }, + { + "name": "close-icon" + } + ], + "events": ["close"], + "snippet": { + "props": { + "title": "Center", + "description": "Displayed in the center of screen." + } + } + }, + "ElTransfer": { + "name": "ElTransfer", + "label": "穿梭框", + "categoryId": "form", + "doc": "https://element-plus.org/zh-CN/component/transfer.html", + "childIncludes": false, + "package": "element-plus", + "props": [ + { + "name": "modelValue", + "defaultValue": "", + "setters": ["ArraySetter", "ExpressionSetter"] + }, + { + "name": "data", + "defaultValue": [], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "filterable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterPlaceholder", + "defaultValue": "Enter keyword", + "setters": "InputSetter" + }, + { + "name": "filterMethod", + "setters": "FunctionSetter" + }, + { + "name": "targetOrder", + "defaultValue": "original", + "options": ["original", "push", "unshift"], + "setters": "SelectSetter" + }, + { + "name": "titles", + "defaultValue": [], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "buttonTexts", + "defaultValue": [], + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "renderContent", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "format", + "defaultValue": "", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "props", + "defaultValue": "", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "leftDefaultChecked", + "defaultValue": [], + "title": "初始状态下左侧列表的已勾选项的 key 数组", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "rightDefaultChecked", + "defaultValue": [], + "title": "初始状态下右侧列表的已勾选项的 key 数组", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + } + ], + "slots": [ + { + "name": "default", + "params": ["options"] + }, + { + "name": "left-footer" + }, + { + "name": "right-footer" + }, + { + "name": "left-empty" + }, + { + "name": "right-empty" + } + ], + "events": [ + { + "name": "change" + }, + { + "name": "left-check-change" + }, + { + "name": "right-check-change" + }, + { + "name": "update:modelValue" + } + ] + }, + "ElTree": { + "name": "ElTree", + "label": "树形控件", + "doc": "https://element-plus.org/zh-CN/component/tree.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "data", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "empty-text", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "node-key", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "props", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "render-after-expand", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "load", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "render-content", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "highlight-current", + "defaultValue": false, + "label": "高亮当前节点", + "setters": "BooleanSetter" + }, + { + "name": "default-expand-all", + "defaultValue": false, + "label": "展开所有节点", + "setters": "BooleanSetter" + }, + { + "name": "expand-on-click-node", + "defaultValue": true, + "title": "是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。", + "label": "点击展开", + "setters": "BooleanSetter" + }, + { + "name": "check-on-click-node", + "defaultValue": false, + "title": "是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。", + "label": "点击选中", + "setters": "BooleanSetter" + }, + { + "name": "auto-expand-parent", + "defaultValue": true, + "title": "展开子节点的时候是否自动展开父节点", + "label": "自动展开", + "setters": "BooleanSetter" + }, + { + "name": "default-expanded-keys", + "defaultValue": "", + "title": "默认展开的节点的 key 的数组", + "label": "默认展开", + "setters": "JSONSetter" + }, + { + "name": "show-checkbox", + "defaultValue": false, + "label": "显示checkbox", + "setters": "BooleanSetter" + }, + { + "name": "check-strictly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "default-checked-keys", + "defaultValue": "", + "title": "默认勾选的节点的 key 的数组", + "label": "默认勾选", + "setters": "JSONSetter" + }, + { + "name": "current-node-key", + "defaultValue": "", + "label": "当前节点key", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "filter-node-method", + "defaultValue": "", + "title": "filter-node-method 对树节点进行筛选时执行的方法, 返回 false 则表示这个节点会被隐藏", + "label": "筛选节点函数", + "setters": "FunctionSetter" + }, + { + "name": "accordion", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "indent", + "defaultValue": 16, + "setters": "NumberSetter" + }, + { + "name": "icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "lazy", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "draggable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allow-drag", + "defaultValue": "", + "title": "判断节点能否被拖拽 如果返回 false ,节点不能被拖动", + "setters": "FunctionSetter" + }, + { + "name": "allow-drop", + "defaultValue": "", + "title": "拖拽时判定目标节点能否成为拖动目标位置。 如果返回 false ,拖动节点不能被拖放到目标节点。 type 参数有三种情况:prev、inner 和 next,分别表示放置在目标节点前、插入至目标节点和放置在目标节点后", + "setters": "FunctionSetter" + } + ], + "events": [ + "node-click", + "node-contextmenu", + "check-change", + "check", + "current-change", + "node-expand", + "node-collapse", + "node-drag-start", + "node-drag-enter", + "node-drag-leave", + "node-drag-over", + "node-drop", + "node-drag-end" + ], + "slots": [ + { + "name": "default", + "params": ["node", "data"] + }, + { + "name": "empty" + } + ], + "snippet": { + "props": { + "data": [ + { + "value": "guide", + "label": "Guide", + "children": [ + { + "value": "disciplines", + "label": "Disciplines", + "children": [ + { + "value": "consistency", + "label": "Consistency" + }, + { + "value": "feedback", + "label": "Feedback" + }, + { + "value": "efficiency", + "label": "Efficiency" + }, + { + "value": "controllability", + "label": "Controllability" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "side nav", + "label": "Side Navigation" + }, + { + "value": "top nav", + "label": "Top Navigation" + } + ] + } + ] + }, + { + "value": "component", + "label": "Component", + "children": [ + { + "value": "basic", + "label": "Basic", + "children": [ + { + "value": "layout", + "label": "Layout" + }, + { + "value": "color", + "label": "Color" + }, + { + "value": "typography", + "label": "Typography" + }, + { + "value": "icon", + "label": "Icon" + }, + { + "value": "button", + "label": "Button" + } + ] + }, + { + "value": "form", + "label": "Form", + "children": [ + { + "value": "radio", + "label": "Radio" + }, + { + "value": "checkbox", + "label": "Checkbox" + }, + { + "value": "input", + "label": "Input" + }, + { + "value": "input-number", + "label": "InputNumber" + }, + { + "value": "select", + "label": "Select" + }, + { + "value": "cascader", + "label": "Cascader" + }, + { + "value": "switch", + "label": "Switch" + }, + { + "value": "slider", + "label": "Slider" + }, + { + "value": "time-picker", + "label": "TimePicker" + }, + { + "value": "date-picker", + "label": "DatePicker" + }, + { + "value": "datetime-picker", + "label": "DateTimePicker" + }, + { + "value": "upload", + "label": "Upload" + }, + { + "value": "rate", + "label": "Rate" + }, + { + "value": "form", + "label": "Form" + } + ] + }, + { + "value": "data", + "label": "Data", + "children": [ + { + "value": "table", + "label": "Table" + }, + { + "value": "tag", + "label": "Tag" + }, + { + "value": "progress", + "label": "Progress" + }, + { + "value": "tree", + "label": "Tree" + }, + { + "value": "pagination", + "label": "Pagination" + }, + { + "value": "badge", + "label": "Badge" + } + ] + }, + { + "value": "notice", + "label": "Notice", + "children": [ + { + "value": "alert", + "label": "Alert" + }, + { + "value": "loading", + "label": "Loading" + }, + { + "value": "message", + "label": "Message" + }, + { + "value": "message-box", + "label": "MessageBox" + }, + { + "value": "notification", + "label": "Notification" + } + ] + }, + { + "value": "navigation", + "label": "Navigation", + "children": [ + { + "value": "menu", + "label": "Menu" + }, + { + "value": "tabs", + "label": "Tabs" + }, + { + "value": "breadcrumb", + "label": "Breadcrumb" + }, + { + "value": "dropdown", + "label": "Dropdown" + }, + { + "value": "steps", + "label": "Steps" + } + ] + }, + { + "value": "others", + "label": "Others", + "children": [ + { + "value": "dialog", + "label": "Dialog" + }, + { + "value": "tooltip", + "label": "Tooltip" + }, + { + "value": "popover", + "label": "Popover" + }, + { + "value": "card", + "label": "Card" + }, + { + "value": "carousel", + "label": "Carousel" + }, + { + "value": "collapse", + "label": "Collapse" + } + ] + } + ] + }, + { + "value": "resource", + "label": "Resource", + "children": [ + { + "value": "axure", + "label": "Axure Components" + }, + { + "value": "sketch", + "label": "Sketch Templates" + }, + { + "value": "docs", + "label": "Design Documentation" + } + ] + } + ] + } + } + }, + "ElTreeSelect": { + "name": "ElTreeSelect", + "label": "树形选择", + "doc": "https://element-plus.org/zh-CN/component/tree-select.html", + "categoryId": "data", + "package": "element-plus", + "props": [ + { + "name": "cacheData", + "label": "cacheData", + "title": "懒加载节点的缓存数据,结构与数据相同,用于获取未加载数据的标签", + "setters": "ArraySetter", + "defaultValue": [] + }, + { + "name": "data", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "empty-text", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "node-key", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "props", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "renderAfterExpand", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "load", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "renderContent", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "highlightCurrent", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "defaultExpandAll", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "expandOnClickNode", + "defaultValue": true, + "title": "是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。", + "setters": "BooleanSetter" + }, + { + "name": "checkOnClickNode", + "defaultValue": false, + "title": "是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。", + "setters": "BooleanSetter" + }, + { + "name": "autoExpandParent", + "defaultValue": true, + "title": "展开子节点的时候是否自动展开父节点", + "setters": "BooleanSetter" + }, + { + "name": "defaultExpandedKeys", + "defaultValue": "", + "title": "默认展开的节点的 key 的数组", + "label": "默认展开", + "setters": "JSONSetter" + }, + { + "name": "showCheckbox", + "defaultValue": false, + "label": "显示checkbox", + "setters": "BooleanSetter" + }, + { + "name": "checkStrictly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "defaultCheckedKeys", + "defaultValue": "", + "title": "默认勾选的节点的 key 的数组", + "label": "默认勾选", + "setters": "JSONSetter" + }, + { + "name": "currentNodeKey", + "defaultValue": "", + "label": "当前节点key", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "filterNodeMethod", + "defaultValue": "", + "title": "filter-node-method 对树节点进行筛选时执行的方法, 返回 false 则表示这个节点会被隐藏", + "label": "筛选节点函数", + "setters": "FunctionSetter" + }, + { + "name": "accordion", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "indent", + "defaultValue": 16, + "setters": "NumberSetter" + }, + { + "name": "icon", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "lazy", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "draggable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowDrag", + "defaultValue": "", + "title": "判断节点能否被拖拽 如果返回 false ,节点不能被拖动", + "setters": "FunctionSetter" + }, + { + "name": "allowDrop", + "defaultValue": "", + "title": "拖拽时判定目标节点能否成为拖动目标位置。 如果返回 false ,拖动节点不能被拖放到目标节点。 type 参数有三种情况:prev、inner 和 next,分别表示放置在目标节点前、插入至目标节点和放置在目标节点后", + "setters": "FunctionSetter" + }, + { + "name": "modelValue", + "defaultValue": "", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "ObjectSetter", "ArraySetter"] + }, + { + "name": "multiple", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "valueKey", + "defaultValue": "value", + "setters": "InputSetter" + }, + { + "name": "size", + "defaultValue": "default", + "options": ["large", "default", "small"], + "setters": "SelectSetter" + }, + { + "name": "clearable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTags", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "collapseTagsTooltip", + "label": "Tooltip", + "title": "当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。 要使用此属性,collapse-tags属性必须设定为 true", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "multipleLimit", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "name", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "effect", + "defaultValue": "light", + "options": ["dark", "light"], + "setters": "SelectSetter" + }, + { + "name": "autocomplete", + "defaultValue": "off", + "setters": "InputSetter" + }, + { + "name": "placeholder", + "defaultValue": "Select", + "setters": "InputSetter" + }, + { + "name": "filterable", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "allowCreate", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "filterMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remote", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "remoteMethod", + "defaultValue": "", + "setters": "FunctionSetter" + }, + { + "name": "remoteShowSuffix", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loading", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "loadingText", + "defaultValue": "Loading", + "setters": "InputSetter" + }, + { + "name": "noMatchText", + "defaultValue": "No matching data", + "setters": "InputSetter" + }, + { + "name": "noDataText", + "defaultValue": "No data", + "setters": "InputSetter" + }, + { + "name": "popperClass", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "reserveKeyword", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "defaultFirstOption", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "popperAppendToBody", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "teleported", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "appendTo", + "setters": "StringSetter" + }, + { + "name": "persistent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "automaticDropdown", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "clearIcon", + "defaultValue": "CircleClose", + "setters": "InputSetter" + }, + { + "name": "fitInputWidth", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "suffixIcon", + "defaultValue": "ArrowUp", + "setters": "InputSetter" + }, + { + "name": "tagType", + "defaultValue": "info", + "options": ["success", "info", "warning", "danger"], + "setters": "SelectSetter" + }, + { + "name": "tagEffect", + "defaultValue": "light", + "options": ["", "light", "dark", "plain"], + "setters": "SelectSetter" + }, + { + "name": "validateEvent", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "offset", + "defaultValue": 12, + "setters": "NumberSetter" + }, + { + "name": "showArrow", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "placement", + "label": "placement", + "title": "下拉框出现的位置", + "setters": "SelectSetter", + "options": [ + "top", + "top-start", + "top-end", + "bottom", + "bottom-start", + "bottom-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end" + ], + "defaultValue": "bottom-start" + }, + { + "name": "fallbackPlacements", + "label": "fallbackPlacements", + "title": "dropdown 可用的 positions", + "setters": "ArraySetter", + "defaultValue": ["bottom-start", "top-start", "right", "left"] + }, + { + "name": "maxCollapseTags", + "label": "maxCollapseTags", + "title": "需要显示的 Tag 的最大数量 只有当 collapse-tags 设置为 true 时才会生效。", + "setters": "NumberSetter", + "defaultValue": 1 + }, + { + "name": "popperOptions", + "label": "popperOptions", + "title": "popper.js 参数", + "setters": "ObjectSetter", + "defaultValue": {} + }, + { + "name": "ariaLabel", + "label": "ariaLabel", + "title": "等价于原生 input aria-label 属性", + "setters": "StringSetter" + }, + { + "name": "emptyValues", + "setters": "ArraySetter" + }, + { + "name": "valueOnClear", + "setters": ["StringSetter", "NumberSetter", "BooleanSetter", "FunctionSetter"] + }, + { + "name": "suffixTransition", + "title": "下拉菜单显示/消失时后缀图标的动画", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "tabindex", + "setters": ["StringSetter", "NumberSetter"] + } + ], + "events": [ + "node-click", + "node-contextmenu", + "check-change", + "check", + "current-change", + "node-expand", + "node-collapse", + "node-drag-start", + "node-drag-enter", + "node-drag-leave", + "node-drag-over", + "node-drop", + "node-drag-end", + "change", + "visible-change", + "remove-tag", + "clear", + "blur", + "focus", + "update:modelValue" + ], + "slots": [ + { + "name": "default", + "params": ["node", "data"] + }, + { + "name": "empty" + }, + { + "name": "header" + }, + { + "name": "footer" + }, + { + "name": "prefix" + }, + { + "name": "empty" + }, + { + "name": "tag" + }, + { + "name": "loading" + }, + { + "name": "label" + } + ], + "snippet": { + "props": { + "data": [ + { + "value": "1", + "label": "Level one 1", + "children": [ + { + "value": "1-1", + "label": "Level two 1-1", + "children": [ + { + "value": "1-1-1", + "label": "Level three 1-1-1" + } + ] + } + ] + }, + { + "value": "2", + "label": "Level one 2", + "children": [ + { + "value": "2-1", + "label": "Level two 2-1", + "children": [ + { + "value": "2-1-1", + "label": "Level three 2-1-1" + } + ] + }, + { + "value": "2-2", + "label": "Level two 2-2", + "children": [ + { + "value": "2-2-1", + "label": "Level three 2-2-1" + } + ] + } + ] + }, + { + "value": "3", + "label": "Level one 3", + "children": [ + { + "value": "3-1", + "label": "Level two 3-1", + "children": [ + { + "value": "3-1-1", + "label": "Level three 3-1-1" + } + ] + }, + { + "value": "3-2", + "label": "Level two 3-2", + "children": [ + { + "value": "3-2-1", + "label": "Level three 3-2-1" + } + ] + } + ] + } + ], + "renderAfterExpand": false, + "style": { + "width": "240px" + } + } + } + }, + "ElTreeV2": { + "name": "ElTreeV2", + "label": "虚拟化树形控件", + "doc": "https://element-plus.org/zh-CN/component/tree-v2.html", + "categoryId": "data", + "childIncludes": false, + "package": "element-plus", + "props": [ + { + "name": "data", + "defaultValue": "", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "empty-text", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "props", + "defaultValue": "", + "setters": ["ObjectSetter", "JSONSetter"] + }, + { + "name": "highlight-current", + "defaultValue": false, + "label": "高亮选中节点", + "setters": "BooleanSetter" + }, + { + "name": "expand-on-click-node", + "defaultValue": true, + "title": "是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点", + "label": "expand-on", + "setters": "BooleanSetter" + }, + { + "name": "check-on-click-node", + "defaultValue": false, + "title": "是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点", + "label": "check-on", + "setters": "BooleanSetter" + }, + { + "name": "default-expanded-keys", + "defaultValue": "", + "title": "默认展开的节点的 key 的数组", + "label": "check-on", + "setters": "JSONSetter" + }, + { + "name": "show-checkbox", + "defaultValue": false, + "title": "节点是否可被选择", + "label": "check-on", + "setters": "BooleanSetter" + }, + { + "name": "check-strictly", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "default-checked-keys", + "defaultValue": "", + "title": "默认勾选的节点的 key 的数组", + "label": "checked-keys", + "setters": "JSONSetter" + }, + { + "name": "current-node-key", + "defaultValue": "", + "label": "选中的节点", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "filter-method", + "defaultValue": "", + "title": "对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示, 返回 false 则表示这个节点会被隐藏", + "setters": "JSONSetter" + }, + { + "name": "indent", + "defaultValue": 16, + "title": "相邻级节点间的水平缩进,单位为像素", + "setters": "NumberSetter" + }, + { + "name": "icon", + "defaultValue": "", + "title": "相邻级节点间的水平缩进,单位为像素", + "setters": "InputSetter" + }, + { + "name": "itemSize ", + "label": "itemSize ", + "title": "自定义树节点的高度", + "setters": "NumberSetter", + "defaultValue": 26 + } + ], + "events": [ + "node-click", + "node-drop", + "node-contextmenu", + "check-change", + "check", + "current-change", + "node-expand", + "node-collapse" + ], + "slots": [ + { + "name": "default", + "params": ["node", "data"] + } + ] + }, + "ElUpload": { + "name": "ElUpload", + "label": "上传", + "doc": "https://element-plus.org/zh-CN/component/upload.html", + "categoryId": "form", + "package": "element-plus", + "props": [ + { + "name": "action", + "defaultValue": "#", + "title": "请求 URL", + "setters": "InputSetter" + }, + { + "name": "headers", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "method", + "defaultValue": "post", + "setters": "InputSetter" + }, + { + "name": "multiple", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "data", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "name", + "defaultValue": "file", + "setters": "ExpressionSetter" + }, + { + "name": "withCredentials", + "defaultValue": false, + "title": "支持发送 cookie 凭证信息", + "setters": "BooleanSetter" + }, + { + "name": "showFileList", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "drag", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "accept", + "defaultValue": "", + "setters": "InputSetter" + }, + { + "name": "crossorigin", + "options": ["", "anonymous", "use-credentials"], + "setters": "SelectSetter" + }, + { + "name": "onPreview", + "setters": "FunctionSetter" + }, + { + "name": "onRemove", + "setters": "FunctionSetter" + }, + { + "name": "onSuccess", + "setters": "FunctionSetter" + }, + { + "name": "onError", + "setters": ["FunctionSetter", "ExpressionSetter"] + }, + { + "name": "onProgress", + "setters": ["FunctionSetter", "ExpressionSetter"] + }, + { + "name": "onChange", + "setters": "FunctionSetter" + }, + { + "name": "onExceed", + "setters": "FunctionSetter" + }, + { + "name": "beforeUpload", + "setters": "FunctionSetter" + }, + { + "name": "beforeRemove", + "setters": "FunctionSetter" + }, + { + "name": "fileList", + "setters": ["ArraySetter", "JSONSetter"] + }, + { + "name": "listType", + "defaultValue": "text", + "options": ["text", "picture", "picture-card"], + "setters": "SelectSetter" + }, + { + "name": "autoUpload", + "defaultValue": true, + "setters": "BooleanSetter" + }, + { + "name": "httpRequest", + "setters": "FunctionSetter" + }, + { + "name": "disabled", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "limit", + "defaultValue": "", + "setters": "NumberSetter" + } + ], + "slots": [ + { + "name": "default" + }, + { + "name": "trigger" + }, + { + "name": "tip" + }, + { + "name": "file" + } + ], + "snippet": { + "props": { + "action": "https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15", + "multiple": true, + "fileList": [ + { + "name": "element-plus-logo.svg", + "url": "https://element-plus.org/images/element-plus-logo.svg" + } + ] + }, + "children": [ + { + "name": "ElButton", + "props": { + "type": "primary" + }, + "children": "选择文件" + } + ] + } + }, + "ElTableV2": { + "name": "ElTableV2", + "label": "虚拟化表格", + "categoryId": "data", + "doc": "https://element-plus.org/zh-CN/component/table-v2.html", + "package": "element-plus", + "props": [ + { + "name": "cache", + "defaultValue": 2, + "setters": "NumberSetter" + }, + { + "name": "estimated-row-height", + "defaultValue": "", + "title": "渲染动态的单元格的预估高度", + "label": "row-height", + "setters": "NumberSetter" + }, + { + "name": "header-class", + "defaultValue": "", + "setters": ["InputSetter", "ExpressionSetter"] + }, + { + "name": "header-props", + "defaultValue": "", + "setters": ["JSONSetter", "ExpressionSetter"] + }, + { + "name": "header-cell-props", + "defaultValue": "", + "setters": ["JSONSetter", "ExpressionSetter"] + }, + { + "name": "header-height", + "defaultValue": 50, + "setters": ["NumberSetter", "ExpressionSetter"] + }, + { + "name": "footer-height", + "defaultValue": 0, + "setters": "NumberSetter" + }, + { + "name": "row-class", + "defaultValue": "", + "setters": ["InputSetter", "ExpressionSetter"] + }, + { + "name": "row-key", + "defaultValue": "id", + "setters": ["InputSetter", "NumberSetter"] + }, + { + "name": "row-props", + "defaultValue": "", + "setters": ["JSONSetter", "ExpressionSetter"] + }, + { + "name": "columns", + "defaultValue": "50", + "setters": "NumberSetter" + }, + { + "name": "data", + "defaultValue": [], + "setters": "JSONSetter" + }, + { + "name": "data-getter", + "defaultValue": "", + "setters": "ExpressionSetter" + }, + { + "name": "fixed-data", + "defaultValue": "", + "setters": "JSONSetter" + }, + { + "name": "expand-column-key", + "defaultValue": "", + "title": "列的 key 来标记哪个行可以被展开", + "label": "column-key", + "setters": "InputSetter" + }, + { + "name": "expanded-row-keys", + "defaultValue": "", + "title": "列的 key 来标记哪个行可以被展开", + "label": "column-key", + "setters": "JSONSetter" + }, + { + "name": "default-expanded-row-keys", + "defaultValue": "", + "title": "默认展开的行的 key 的数组, 这个数据不是响应式的", + "label": "默认展开行", + "setters": "JSONSetter" + }, + { + "name": "class", + "defaultValue": "", + "setters": ["JSONSetter", "InputSetter"] + }, + { + "name": "fixed", + "defaultValue": false, + "setters": "BooleanSetter" + }, + { + "name": "width *", + "defaultValue": "", + "label": "表宽必填", + "setters": "NumberSetter" + }, + { + "name": "height *", + "defaultValue": "", + "label": "表高必填", + "setters": "NumberSetter" + }, + { + "name": "max-height", + "defaultValue": "", + "setters": "NumberSetter" + }, + { + "name": "h-scrollbar-size", + "defaultValue": 6, + "label": "水平滚动条大小", + "setters": "NumberSetter" + }, + { + "name": "h-scrollbar-size", + "defaultValue": 6, + "label": "垂直滚动条大小", + "setters": "NumberSetter" + }, + { + "name": "scrollbar-always-on", + "defaultValue": false, + "title": "如果开启,滚动条将一直显示,反之只会在鼠标经过时显示。", + "label": "scrollbar", + "setters": "BooleanSetter" + }, + { + "name": "sort-by", + "defaultValue": {}, + "title": "排序方式", + "setters": "JSONSetter" + }, + { + "name": "sort-state", + "title": "多个排序", + "setters": "JSONSetter" + } + ], + "slots": ["cell", "header", "header-cell", "row", "footer", "empty", "overlay"], + "events": [ + "column-sort", + "expanded-rows-change", + "end-reached", + "scroll", + "rows-rendered", + "row-event-handlers" + ] + }, + "ElWatermark": { + "name": "ElWatermark", + "label": "水印", + "categoryId": "other", + "doc": "https://element-plus.org/zh-CN/component/watermark.html", + "package": "element-plus", + "props": [ + { + "name": "width", + "label": "width", + "title": "水印的宽度, content 的默认值是它自己的宽度", + "setters": "NumberSetter", + "defaultValue": 120 + }, + { + "name": "height", + "label": "height", + "title": "水印的高度, content 的默认值是它自己的高度", + "setters": "NumberSetter", + "defaultValue": 64 + }, + { + "name": "rotate", + "label": "rotate", + "title": "水印的旋转角度, 单位 °", + "setters": "NumberSetter", + "defaultValue": -22 + }, + { + "name": "zIndex", + "label": "zIndex", + "title": "水印元素的z-index值", + "setters": "NumberSetter", + "defaultValue": 9 + }, + { + "name": "image", + "label": "image", + "title": "水印图片,建议使用 2x 或 3x 图像", + "setters": "StringSetter" + }, + { + "name": "content", + "label": "content", + "title": "水印文本内容", + "setters": ["StringSetter", "ArraySetter"] + }, + { + "name": "font", + "label": "font", + "title": "文字样式", + "setters": "ObjectSetter", + "defaultValue": { + "color": "rgba(0,0,0,.15)", + "fontSize": 16, + "fontWeight": "normal", + "fontFamily": "sans-serif", + "fontStyle": "normal", + "textAlign": "center", + "textBaseline": "top" + } + }, + { + "name": "gap", + "label": "gap", + "title": "水印之间的间距", + "setters": "ArraySetter", + "defaultValue": [100, 100] + }, + { + "name": "offset", + "label": "offset", + "title": "水印从容器左上角的偏移 默认值为 gap/2", + "setters": "ArraySetter", + "defaultValue": [50, 50] + } + ], + "slots": ["default"], + "snippet": { + "props": { + "font": { + "color": "rgba(0, 0, 0, .15)" + } + }, + "children": [ + { + "name": "div", + "props": { + "style": { + "height": "500px" + } + } + } + ] + } + }, + "XChart": { + "name": "XChart", + "label": "图表", + "categoryId": "base", + "props": [ + { + "name": "option", + "label": "option", + "title": "ECharts option", + "setters": "ObjectSetter" + }, + { + "name": "width", + "label": "width", + "setters": ["StringNumber"] + }, + { + "name": "height", + "label": "height", + "setters": ["StringNumber"] + } + ], + "snippet": { + "props": { + "width": "100%", + "height": "400px", + "option": { + "xAxis": { + "type": "category", + "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + }, + "yAxis": { + "type": "value" + }, + "series": [ + { + "data": [150, 230, 224, 218, 135, 147, 260], + "type": "line" + } + ] + } + } + }, + "package": "@vtj/charts" + } +} diff --git a/.vtj/projects/vue-element-plus-admin.json b/.vtj/projects/vue-element-plus-admin.json new file mode 100644 index 000000000..455f8b1e6 --- /dev/null +++ b/.vtj/projects/vue-element-plus-admin.json @@ -0,0 +1,179 @@ +{ + "__VTJ_PROJECT__": true, + "id": "vue-element-plus-admin", + "name": "ElementAdmin", + "homepage": "", + "description": "一套基于vue3、element-plus、typesScript、vite4的后台集成方案。", + "dependencies": [ + { + "package": "vue", + "version": "latest", + "library": "Vue", + "urls": ["@vtj/materials/deps/vue/vue.global.prod.js"], + "assetsLibrary": "VueMaterial", + "required": true, + "official": true, + "enabled": true + }, + { + "package": "vue-router", + "version": "latest", + "library": "VueRouter", + "urls": ["@vtj/materials/deps/vue-router/vue-router.global.prod.js"], + "assetsLibrary": "VueRouterMaterial", + "required": true, + "official": true, + "enabled": true + }, + { + "package": "@vtj/utils", + "version": "latest", + "library": "VtjUtils", + "urls": ["@vtj/materials/deps/@vtj/utils/index.umd.js"], + "required": true, + "official": true, + "enabled": true + }, + { + "package": "@vtj/icons", + "version": "latest", + "library": "VtjIcons", + "urls": [ + "@vtj/materials/deps/@vtj/icons/style.css", + "@vtj/materials/deps/@vtj/icons/index.umd.js" + ], + "required": true, + "official": true, + "enabled": true + }, + { + "package": "@vueuse/core", + "version": "latest", + "library": "VueUse", + "urls": [ + "@vtj/materials/deps/@vueuse/shared/index.iife.min.js", + "@vtj/materials/deps/@vueuse/core/index.iife.min.js" + ], + "required": false, + "official": true, + "enabled": true + }, + { + "package": "element-plus", + "version": "latest", + "library": "ElementPlus", + "localeLibrary": "ElementPlusLocaleZhCn", + "urls": [ + "@vtj/materials/deps/element-plus/dark/css-vars.css", + "@vtj/materials/deps/element-plus/index.css", + "@vtj/materials/deps/element-plus/zh-cn.js", + "@vtj/materials/deps/element-plus/index.full.min.js" + ], + "assetsUrl": "@vtj/materials/assets/element/index.umd.js", + "assetsLibrary": "ElementPlusMaterial", + "required": false, + "official": true, + "enabled": true + }, + { + "package": "@vtj/ui", + "version": "latest", + "library": "VtjUI", + "urls": [ + "@vtj/materials/deps/vxe-table/style.min.css", + "@vtj/materials/deps/@vtj/ui/style.css", + "@vtj/materials/deps/xe-utils/xe-utils.umd.min.js", + "@vtj/materials/deps/vxe-table/index.umd.min.js", + "@vtj/materials/deps/@vtj/ui/index.umd.js" + ], + "assetsUrl": "@vtj/materials/assets/ui/index.umd.js", + "assetsLibrary": "VtjUIMaterial", + "required": false, + "official": true, + "enabled": true + }, + { + "package": "@vtj/charts", + "version": "latest", + "library": "VtjCharts", + "urls": [ + "@vtj/materials/deps/echarts/echarts.min.js", + "@vtj/materials/deps/@vtj/charts/index.umd.js" + ], + "assetsUrl": "@vtj/materials/assets/charts/index.umd.js", + "assetsLibrary": "VtjChartsMaterial", + "required": false, + "official": true, + "enabled": true + }, + { + "package": "ant-design-vue", + "version": "latest", + "library": "antd", + "urls": [ + "@vtj/materials/deps/ant-design-vue/reset.css", + "@vtj/materials/deps/ant-design-vue/dayjs/dayjs.min.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/customParseFormat.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/weekday.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/localeData.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/weekOfYear.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/weekYear.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/advancedFormat.js", + "@vtj/materials/deps/ant-design-vue/dayjs/plugin/quarterOfYear.js", + "@vtj/materials/deps/ant-design-vue/antd.min.js" + ], + "assetsUrl": "@vtj/materials/assets/antdv/index.umd.js", + "assetsLibrary": "AntdvMaterial", + "required": false, + "official": true, + "enabled": false + }, + { + "package": "vant", + "version": "latest", + "library": "vant", + "urls": ["@vtj/materials/deps/vant/index.css", "@vtj/materials/deps/vant/vant.min.js"], + "assetsUrl": "@vtj/materials/assets/vant/index.umd.js", + "assetsLibrary": "VantMaterial", + "required": false, + "official": true, + "enabled": false + } + ], + "pages": [ + { + "dir": true, + "name": "System", + "title": "系统管理", + "icon": "ChromeFilled", + "hidden": false, + "prue": false, + "id": "45rmet3ni", + "type": "page", + "children": [ + { + "dir": false, + "name": "Users", + "title": "用户管理", + "icon": "", + "mask": true, + "hidden": false, + "raw": false, + "prue": false, + "meta": "", + "cache": false, + "id": "7pdk4mxyf", + "type": "page", + "market": { + "id": "0290db4d-f64e-4119-b62d-1e0b56193d6f" + } + } + ] + } + ], + "blocks": [], + "apis": [], + "meta": [], + "config": {}, + "__BASE_PATH__": "/" +} diff --git a/.vtj/vue/7pdk4mxyf.vue b/.vtj/vue/7pdk4mxyf.vue new file mode 100644 index 000000000..0523cac2b --- /dev/null +++ b/.vtj/vue/7pdk4mxyf.vue @@ -0,0 +1,222 @@ + + + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..f75b9b986 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1391 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [2.8.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.8.0...v2.8.1) (2024-06-20) + + +### Bug Fixes + +* [#458](https://github.com/kailong321200875/vue-element-plus-admin/issues/458) ([49451ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/49451ae606009d1f5ab0b98f84535892d3fd7646)) +* [#481](https://github.com/kailong321200875/vue-element-plus-admin/issues/481) ([c77586c](https://github.com/kailong321200875/vue-element-plus-admin/commit/c77586c5670cdc63978b032bbda694a14e875838)) +* 修复 search组件的收起展开 和重置 Bug ([9a5c7bc](https://github.com/kailong321200875/vue-element-plus-admin/commit/9a5c7bcb5b51e76eac6bc1d3aebc287593b13ca1)) +* 修复css前缀无法应用问题([#482](https://github.com/kailong321200875/vue-element-plus-admin/issues/482)) ([4b43c87](https://github.com/kailong321200875/vue-element-plus-admin/commit/4b43c87949fe4a68b4be004a06dfff4c7f87fbd4)) +* 修复表格default-expand-all属性无效BUG ([6657bbc](https://github.com/kailong321200875/vue-element-plus-admin/commit/6657bbc9f11f22cbfb04a57f5629bc810575496e)) +* 修复表格合计报错问题 ([9c44006](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c44006ec26bee446dc5c90b6a4546cdd84ba4dc)) + + +### Styling + +* 修改登录页样式 ([9f98b7b](https://github.com/kailong321200875/vue-element-plus-admin/commit/9f98b7be266825612f93135c460d7db2d6a8beb0)) + + +### Performance Improvements + +* 优化使用离线图标后运行慢问题 ([7e9c4a6](https://github.com/kailong321200875/vue-element-plus-admin/commit/7e9c4a6109b417a577d9ac9ecf02db52eb1964af)) + +## [2.8.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.7.0...v2.8.0) (2024-06-01) + + +### Types + +* 修复Table类型错误 ([79b917a](https://github.com/kailong321200875/vue-element-plus-admin/commit/79b917af4957aa4b47db46e034385477828f5fca)) + + +### Features + +* Add a new component CodeEditor ([#466](https://github.com/kailong321200875/vue-element-plus-admin/issues/466)) ([00989b7](https://github.com/kailong321200875/vue-element-plus-admin/commit/00989b7ac9b92685be495c15c1f11dd2546eb6be)) + + +### Bug Fixes + +* [#427](https://github.com/kailong321200875/vue-element-plus-admin/issues/427) ([a00d76e](https://github.com/kailong321200875/vue-element-plus-admin/commit/a00d76e4149b430e19c985a78b9d89ce992dba3f)) +* [#428](https://github.com/kailong321200875/vue-element-plus-admin/issues/428) ([97a1cd4](https://github.com/kailong321200875/vue-element-plus-admin/commit/97a1cd41de82dad8855c95cec6bb106541fd53a7)) +* [#432](https://github.com/kailong321200875/vue-element-plus-admin/issues/432) ([df5b716](https://github.com/kailong321200875/vue-element-plus-admin/commit/df5b7166b48b7e0e77a1fb10ab6dd353d186547e)) +* [#438](https://github.com/kailong321200875/vue-element-plus-admin/issues/438) ([f977fdb](https://github.com/kailong321200875/vue-element-plus-admin/commit/f977fdb05d018ee07baeb6db454b9a77acb89f07)) +* [#451](https://github.com/kailong321200875/vue-element-plus-admin/issues/451) ([08665a3](https://github.com/kailong321200875/vue-element-plus-admin/commit/08665a35ac606549322039d073daf8072053eef4)) +* [#465](https://github.com/kailong321200875/vue-element-plus-admin/issues/465) ([8996e01](https://github.com/kailong321200875/vue-element-plus-admin/commit/8996e01ca35bfad8c13bef321f86bdd711202e12)) +* less 变量命名与 css 关键字冲突 [#475](https://github.com/kailong321200875/vue-element-plus-admin/issues/475) ([1c56e13](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c56e13c5523a86d77464eccee26b5408db028c7)) +* 修复 lint-staged 中 prettier 以 json 格式美化代码的无效命令问题 ([7b2eae1](https://github.com/kailong321200875/vue-element-plus-admin/commit/7b2eae1d6aa813e162c3ad4a0553d2df480c765f)) +* 修复 Transfer 组件 optionApi 不生效 ([198718b](https://github.com/kailong321200875/vue-element-plus-admin/commit/198718b8749a036263d756f928b5dd38cfb47701)) +* 修复富文本编辑器初始化时, 报错 Error: Cannot find a descendant at path [0,1] in node ([a65d5fd](https://github.com/kailong321200875/vue-element-plus-admin/commit/a65d5fd20334307a56cb469361e8f9bd838510c9)) +* 修复组件-查询界面:收起和展开功能bug [#473](https://github.com/kailong321200875/vue-element-plus-admin/issues/473) ([8e58eae](https://github.com/kailong321200875/vue-element-plus-admin/commit/8e58eaeed6ea9beb749afaed75edc5a4f6d9867a)) + + +### Docs + +* 更新群二维码 ([2c89dbc](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c89dbc884c38511d40c92480f65aef46511cefb)) + + +### Performance Improvements + +* 已经是 FormData 对象的不用再次转换 ([d582ad4](https://github.com/kailong321200875/vue-element-plus-admin/commit/d582ad428f4b378014d063635c4afbbad944a71a)) + +## [2.7.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.6.0...v2.7.0) (2024-02-29) + + +### Features + +* IAgree ([abb6906](https://github.com/kailong321200875/vue-element-plus-admin/commit/abb69064dfdb979e2843e3a1b62a2510f6ed3637)) +* 头像列表 ([3bf28a5](https://github.com/kailong321200875/vue-element-plus-admin/commit/3bf28a5d4555bf2a10754474db81d70b04ee432a)) +* 新增个人中心页 ([4146716](https://github.com/kailong321200875/vue-element-plus-admin/commit/4146716655bfbe4ae5b780e5b52a6377efd914ec)) + + +### Bug Fixes + +* 修复启动慢问题 ([61d7ef6](https://github.com/kailong321200875/vue-element-plus-admin/commit/61d7ef642a027e9e1f942bc84322233be3ca9a82)) +* 修复第四种布局样式层级问题([#424](https://github.com/kailong321200875/vue-element-plus-admin/issues/424)) ([78aeb89](https://github.com/kailong321200875/vue-element-plus-admin/commit/78aeb897fc93cfb998f94578d1fbe4480426843f)) + + +### Docs + +* 更新群二维码 ([c8c1a1b](https://github.com/kailong321200875/vue-element-plus-admin/commit/c8c1a1b6357105da73e23adff968c3f2fad7d837)) + +## [2.6.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.6...v2.6.0) (2024-02-07) + + +### Features + +* add vite-plugin-url-copy ([f5ab977](https://github.com/kailong321200875/vue-element-plus-admin/commit/f5ab9776a90e0136b243601571f4619c20da3ccd)) + + +### Bug Fixes + +* Table组件中size属性的validator设置错误 ([f30e37e](https://github.com/kailong321200875/vue-element-plus-admin/commit/f30e37ee777d4f30d4ae58c4a016a1392d41c25f)) +* Table组件注册为全局组件报错问题,存在对pinia的提前引用 ([1e209a7](https://github.com/kailong321200875/vue-element-plus-admin/commit/1e209a702a5114943a615063eefd0c00f1a6a003)) +* Table组件设置 align="center" 导致横向滚动条位置错误问题 ([22f071d](https://github.com/kailong321200875/vue-element-plus-admin/commit/22f071d9268806f7abd23ab2d08e9392e377a426)) +* 修复 element-plus 2.5版本以上,el-form-item inline模式下,select宽度问题 ([f44e48d](https://github.com/kailong321200875/vue-element-plus-admin/commit/f44e48d08d3f8dd347b829166107dd62e5e18c72)) +* 修复 prettier 报错 ([f5f08f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/f5f08f8f87b063d489f55ea8f19c7c802acf15f7)) +* 修复 useCrudSchemas 详情组件数据结构文案不匹配问题 ([d94fc0a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d94fc0a701bcbc9343ab3e7b630e3db8f6d61623)) +* 修复cutMenu布局刷新样式问题 ([03580b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/03580b0ca0c8d088589ae1d8426b1535f654361b)) +* 修复Menu组件缩略菜单弹窗内样式不统一问题 ([d5dc4e3](https://github.com/kailong321200875/vue-element-plus-admin/commit/d5dc4e32d5978fcd271e841832c9cbf1e0c87db7)) +* 修复TagsView右键菜单逻辑错误 ([901c891](https://github.com/kailong321200875/vue-element-plus-admin/commit/901c891872ef6164e3517eb8e798d6039b7b7f4e)) +* 修复test打包VITE_USE_ONLINE_ICON无效问题 ([a3436a3](https://github.com/kailong321200875/vue-element-plus-admin/commit/a3436a32c6fd746e9e2af67c3cc5a8872aabf919)) +* 修复本地化图标空白问题 ([14ff83a](https://github.com/kailong321200875/vue-element-plus-admin/commit/14ff83affcd267fbdb405d2f46e9f929a1fbfaeb)) +* 修复请求示例中,mock开启时无法取消单个请求的问题 ([d6d70a4](https://github.com/kailong321200875/vue-element-plus-admin/commit/d6d70a443cccb2fe12161b57a1f227d1ed63384a)) +* 修改兼容方式,兼容Form 组件中contentMap中类输入框或下拉选择的所有组件,特殊兼容 InputNumber 组件 ([ab98ceb](https://github.com/kailong321200875/vue-element-plus-admin/commit/ab98ceb85f52c5f7b87c2114997c63f1b80f216f)) +* 更换判断条件 ([b5cb626](https://github.com/kailong321200875/vue-element-plus-admin/commit/b5cb626bfac4df8b1a0741b5000d5b22f6cd4555)) + + +### Docs + +* 修改群二维码 ([395ff68](https://github.com/kailong321200875/vue-element-plus-admin/commit/395ff68412ff71a9b8ce670c2399da285cfed67d)) +* 更新群二维码 ([c8ccaa8](https://github.com/kailong321200875/vue-element-plus-admin/commit/c8ccaa8d49b5bf7a2784a29af6e126657ce54cda)) + + +### Styling + +* 添加TabMenu边框 ([feb3d9a](https://github.com/kailong321200875/vue-element-plus-admin/commit/feb3d9a8d07f6444c39ca89f6eb63245c06783a0)) + +## [2.5.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.5...v2.5.6) (2024-01-18) + + +### Bug Fixes + +* [#396](https://github.com/kailong321200875/vue-element-plus-admin/issues/396) ([9b2b4d4](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b2b4d42a6d5fffd5012506b7cac3892774c8595)) +* [#399](https://github.com/kailong321200875/vue-element-plus-admin/issues/399) ([59d4ed4](https://github.com/kailong321200875/vue-element-plus-admin/commit/59d4ed4dd9d6b6f0d5881b4d466e7a621770ad75)) +* 修复Form组件设置了hidden还是会出现占位空白 ([0f531fd](https://github.com/kailong321200875/vue-element-plus-admin/commit/0f531fd1d0469ddd56327b0a9a7956a0d6076c91)) +* 修复无法登录问题 ([8ce00ab](https://github.com/kailong321200875/vue-element-plus-admin/commit/8ce00ab247de4061cb56f9c2f6d3079abd39aefd)) +* 修复菜单管理回显问题 ([d9ca9ba](https://github.com/kailong321200875/vue-element-plus-admin/commit/d9ca9ba5e8111b7cc3758a8bba14f7fac45c9446)) +* 升级依赖,修复vue警告 ([eafb507](https://github.com/kailong321200875/vue-element-plus-admin/commit/eafb5075d587feac0501a1adae90a176a72c240f)) + + +### Docs + +* 更新README ([28bd10f](https://github.com/kailong321200875/vue-element-plus-admin/commit/28bd10f26373ad6e139b412e08d1e2afacc4ab92)) + + +### Styling + +* 调整样式 ([09b96c7](https://github.com/kailong321200875/vue-element-plus-admin/commit/09b96c75425cd2d931e7df4ef3f330b78bf74f9e)) + + +### Performance Improvements + +* request请求根据ContentType自动转换数据 ([ef9aa62](https://github.com/kailong321200875/vue-element-plus-admin/commit/ef9aa625724b754afc565b8b1f2589376f4d5c50)) +* 使用flex布局,优化section区域min-height的繁琐计算 ([fbb6f9a](https://github.com/kailong321200875/vue-element-plus-admin/commit/fbb6f9ad4b6d5fac9bb95d0a9250b5a318680d99)) + +## [2.5.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.4...v2.5.5) (2024-01-06) + + +### Bug Fixes + +* [#276](https://github.com/kailong321200875/vue-element-plus-admin/issues/276) ([6fbc2b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/6fbc2b0243e4aec0463a734c37591dc3de40f7db)) +* el-button组件和其他部分使用到相关变量的组件无法适配主题色变化问题 ([00cac6a](https://github.com/kailong321200875/vue-element-plus-admin/commit/00cac6a831c2a0bb2f8a9df8b9264f1cad13ddde)) + + +### Styling + +* 菜单支持超出省略号 ([a926c56](https://github.com/kailong321200875/vue-element-plus-admin/commit/a926c5607a162145f77d35762b3d6730d67b23f6)) +* 菜单背景支持跟随暗黑模式 ([b34aeba](https://github.com/kailong321200875/vue-element-plus-admin/commit/b34aeba10a464a0f92752fc966386286443df53a)) + + +### Performance Improvements + +* 优化ImageCropping ([069777c](https://github.com/kailong321200875/vue-element-plus-admin/commit/069777c8801c51ab28c070b2ba3f10000e9c91b4)) +* 图标选择器逻辑优化 ([c2dde25](https://github.com/kailong321200875/vue-element-plus-admin/commit/c2dde252297c94036221d5d9971781182bc2998e)) +* 表格组件预览字段拆分 ([8c5858e](https://github.com/kailong321200875/vue-element-plus-admin/commit/8c5858e2c5d42db1de37d5290ea2ca784f4d4612)) + +## [2.5.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.3...v2.5.4) (2023-12-26) + + +### Types + +* 修复全局组件属性类型无法推导 ([94160c0](https://github.com/kailong321200875/vue-element-plus-admin/commit/94160c0418816e560f440e259e1f0fd4742e0143)) + + +### Bug Fixes + +* Menu菜单组件显示bug,renderMenuItem返回的数组存在undefined数据,导致省略菜单显示问题 ([1c63757](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c63757d55076d15ffdf21d647de393ca3c6b0be)) +* useClipboard在ip地址下不能使用问题 ([f3593c4](https://github.com/kailong321200875/vue-element-plus-admin/commit/f3593c453a8b8d5eb8cbd0ed5402132b027461b9)) +* 修复request请求自定义headers类型错误 ([bf2cd72](https://github.com/kailong321200875/vue-element-plus-admin/commit/bf2cd720d0e5801603848a0b1520a928443ac549)) +* 修复切换主题色缓存失败 ([1074520](https://github.com/kailong321200875/vue-element-plus-admin/commit/10745207e64d2d444636cb9d877cec9a0bebf1eb)) +* 修复非正式环境打包报错 ([3a5db42](https://github.com/kailong321200875/vue-element-plus-admin/commit/3a5db42c97f382f3fc701b8f113385b38a214583)) + + +### Styling + +* 本地化图标 ([608bf50](https://github.com/kailong321200875/vue-element-plus-admin/commit/608bf50e1cae49b7f97587395f794ae351f833f0)) +* 添加常见问题链接 ([16b9375](https://github.com/kailong321200875/vue-element-plus-admin/commit/16b93757d32c8ce2f611a62d6015072b0ecfc09a)) + + +### Code Refactoring + +* 新增列设置 ([7314065](https://github.com/kailong321200875/vue-element-plus-admin/commit/7314065c907f8ef4d184c1f3c724b67c30410ab9)) +* 重写useEventBus ([8035151](https://github.com/kailong321200875/vue-element-plus-admin/commit/80351516ced0ec2d67c30405d4a644aca8ca4bc2)) + + +### Performance Improvements + +* 优化启动速度 ([379b340](https://github.com/kailong321200875/vue-element-plus-admin/commit/379b340750eb0d4f7816f5d7c25cbd2983fd33b9)) +* 还原mock.js ([83de387](https://github.com/kailong321200875/vue-element-plus-admin/commit/83de387e2a0124804a9c99080ac841a9d6676fca)) + +## [2.5.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.2...v2.5.3) (2023-12-17) + + +### Bug Fixes + +* [#374](https://github.com/kailong321200875/vue-element-plus-admin/issues/374) ([30fb2de](https://github.com/kailong321200875/vue-element-plus-admin/commit/30fb2de6f37fe0bb00b0f364da31b07a292d59a1)) +* 修复cutMenu布局和top布局内容高度计算错误问题 ([8badd48](https://github.com/kailong321200875/vue-element-plus-admin/commit/8badd48a699aabd8fe510052d098fa6848ff5cbd)) +* 修复动态路由多开标签页404问题 ([1c5b16f](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c5b16f529d2e60a1eefcadf3f416585d1adb93b)) +* 修复类型推导错误 ([649fb17](https://github.com/kailong321200875/vue-element-plus-admin/commit/649fb17d000c0d500ffcfe1f9ab6ddd73ab7ecfa)) +* 修复项目配置清楚缓存无效 ([a09ee60](https://github.com/kailong321200875/vue-element-plus-admin/commit/a09ee60bb123f5bc4bbe6d80539145d5c4b94cb8)) + + +### Code Refactoring + +* 重构描述组件样式 ([c7658d8](https://github.com/kailong321200875/vue-element-plus-admin/commit/c7658d8c70618045a7527156444ba1d564963325)) + + +### Performance Improvements + +* 优化登录记住我流程 ([2009594](https://github.com/kailong321200875/vue-element-plus-admin/commit/2009594f089722151b739598dbad5ee7fb062b6e)) + +## [2.5.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.1...v2.5.2) (2023-12-10) + + +### Bug Fixes + +* 修复mock无法使用问题 ([319aaef](https://github.com/kailong321200875/vue-element-plus-admin/commit/319aaef7eec6287a0e80f25a479918d43c051810)) + +## [2.5.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.5.0...v2.5.1) (2023-12-10) + + +### Bug Fixes + +* 修复表单回车刷新页面 ([2f64836](https://github.com/kailong321200875/vue-element-plus-admin/commit/2f6483652b5d130057b4422b0f3350542b4b4b1d)) +* 表单布局方式为top时,查询组件按钮位置错位 ([ca98359](https://github.com/kailong321200875/vue-element-plus-admin/commit/ca983590da72cb13392cb8897f4045fbacbc6c8d)) + + +### Docs + +* 更新Readme ([81d2dc6](https://github.com/kailong321200875/vue-element-plus-admin/commit/81d2dc6a43df8fd5799461cdafc1b7e6054cf1e1)) + + +### Styling + +* 修改视频表格样式 ([93767b6](https://github.com/kailong321200875/vue-element-plus-admin/commit/93767b65aa7c41e28a8a79a82edd2a91d20bd176)) +* 抽离BaseButton,支持按钮修改主题色 ([69539ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/69539ee2d34ddfcb83cbfb25e218b94891196e76)) + + +### Performance Improvements + +* [#344](https://github.com/kailong321200875/vue-element-plus-admin/issues/344) ([7fa533b](https://github.com/kailong321200875/vue-element-plus-admin/commit/7fa533b8ba0d886c0009b350a3b5fe4b027a9126)) + +## [2.5.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.4.1...v2.5.0) (2023-12-03) + + +### Types + +* 删除无用类型 ([30e4214](https://github.com/kailong321200875/vue-element-plus-admin/commit/30e421438793b8283a0113ba50eb9aef90cfed4e)) + + +### Features + +* VideoPlayer ([7b5bbed](https://github.com/kailong321200875/vue-element-plus-admin/commit/7b5bbedbccf56049ff611005ba17a0f07b07034d)) +* 持久化缓存 ([893459d](https://github.com/kailong321200875/vue-element-plus-admin/commit/893459da7cf819b6b94477cd76fdfeeecacc287f)) +* 新增ImageCropping ([b0a43a7](https://github.com/kailong321200875/vue-element-plus-admin/commit/b0a43a70e6c93690ba4b0779527316f40297a45d)) +* 新增userStore ([77c962e](https://github.com/kailong321200875/vue-element-plus-admin/commit/77c962ea91de68299a01680a7941cf7a73c7e4a7)) +* 新增表格视频预览 ([cfc2d54](https://github.com/kailong321200875/vue-element-plus-admin/commit/cfc2d54586e73353295e7b73e2bf39e4e4d03c96)) +* 替换mock-server插件 ([b8f9a99](https://github.com/kailong321200875/vue-element-plus-admin/commit/b8f9a9940d5eb3f532421b1b85aeb1f3d9afb4b1)) +* 替换mockjs ([7c76d94](https://github.com/kailong321200875/vue-element-plus-admin/commit/7c76d945be8c46b427fe65c728ae0e70ab7a5e91)) +* 重新整理目录结构,mock请求 ([179ab26](https://github.com/kailong321200875/vue-element-plus-admin/commit/179ab2672fe7fff55c8a9c55fae22a4b6c362623)) + + +### Bug Fixes + +* [#367](https://github.com/kailong321200875/vue-element-plus-admin/issues/367) ([c8400ab](https://github.com/kailong321200875/vue-element-plus-admin/commit/c8400abd9f37405127890be1c9a559edf9f251f8)) + + +### Styling + +* 格式化代码 ([31ea31d](https://github.com/kailong321200875/vue-element-plus-admin/commit/31ea31dde8a149f4fc805c08e4fca4e755c36752)) +* 表单项宽度默认100% ([416de2b](https://github.com/kailong321200875/vue-element-plus-admin/commit/416de2b4d644f68d7db379c7cb1139c8a17f64d7)) + + +### Performance Improvements + +* 新增token过期示例 ([bdc8d35](https://github.com/kailong321200875/vue-element-plus-admin/commit/bdc8d358a1ca8f5fc6b43990899834791364e4f2)) + +## [2.4.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.4.0...v2.4.1) (2023-11-12) + + +### Bug Fixes + +* [#361](https://github.com/kailong321200875/vue-element-plus-admin/issues/361) ([2e7797b](https://github.com/kailong321200875/vue-element-plus-admin/commit/2e7797be68b2469d979231e6588b43d0b5bdb88b)) +* Default currentSize ([af583c7](https://github.com/kailong321200875/vue-element-plus-admin/commit/af583c71b0d1760ba4ed4cfa12458820c3f4db52)) +* 修复瀑布流示例图片无法展示 ([3477173](https://github.com/kailong321200875/vue-element-plus-admin/commit/3477173b7649eb43a1e64c91135b0e657a3c7888)) +* 修复自动格式化无效 ([bd82108](https://github.com/kailong321200875/vue-element-plus-admin/commit/bd8210858126f945bad31b3f1e0416aa178afef1)) + + +### Styling + +* 修改样式 ([92d436b](https://github.com/kailong321200875/vue-element-plus-admin/commit/92d436b8bb95c94831fcfe30678d384c3debc052)) + + +### Performance Improvements + +* 优化权限管理 ([efc1c25](https://github.com/kailong321200875/vue-element-plus-admin/commit/efc1c25db86d28438a2c324a3dc302501e1fdf8f)) +* 优化瀑布流组件 ([82eb7f1](https://github.com/kailong321200875/vue-element-plus-admin/commit/82eb7f16ad3f663be602a747b55a78f6b986da30)) + +## [2.4.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.3.0...v2.4.0) (2023-10-14) + + +### Types + +* 修改类型错误 ([4760733](https://github.com/kailong321200875/vue-element-plus-admin/commit/4760733bbe39b547285894555754bae6539190f9)) + + +### Features + +* Waterfall ([d543e56](https://github.com/kailong321200875/vue-element-plus-admin/commit/d543e56efb3b3e5800ab3ec24eda25565311eda2)) + + +### Bug Fixes + +* [#342](https://github.com/kailong321200875/vue-element-plus-admin/issues/342) ([1c51221](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c512216453b17c64a09f97263fd481816badf7c)) +* [#346](https://github.com/kailong321200875/vue-element-plus-admin/issues/346) ([d392868](https://github.com/kailong321200875/vue-element-plus-admin/commit/d392868c2799c2066ba606b0cdad95c011399559)) +* [#355](https://github.com/kailong321200875/vue-element-plus-admin/issues/355) ([03d5e13](https://github.com/kailong321200875/vue-element-plus-admin/commit/03d5e130146a662a8a312e6c49f995f85ea0f9d3)) +* **Descriptions:** Add a default value ([83b09f0](https://github.com/kailong321200875/vue-element-plus-admin/commit/83b09f09ffafb2a6273a1c5274e22f842c202c32)) +* table column 中定义 selectable 无效 ([b8e043c](https://github.com/kailong321200875/vue-element-plus-admin/commit/b8e043c09c74fe00521ac0d7390331b9f223c797)) +* Table的addColumn不能添加首列 ([240178f](https://github.com/kailong321200875/vue-element-plus-admin/commit/240178fd380402571fc056ddb9c8ae44ccb1e265)) +* 修复Waterfall列数错误BUG ([1c2befa](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c2befa4ddc76c625774100e3f5dd5a68a6faa45)) +* 去除控制台警告 ([4d14246](https://github.com/kailong321200875/vue-element-plus-admin/commit/4d14246de50d2ba9d652ec5ef038f4fd3597006a)) + + +### Styling + +* Descriptions样式调整 ([be73f4d](https://github.com/kailong321200875/vue-element-plus-admin/commit/be73f4da3e4bbbacf3f748f7ebfd70f825e0d15e)) +* formDemo集成图标选择器 ([99ffe6a](https://github.com/kailong321200875/vue-element-plus-admin/commit/99ffe6a86ac9961ad5b9be0171b01acdfa0cf994)) +* 修改 Search 组件图标错误 ([7c93b74](https://github.com/kailong321200875/vue-element-plus-admin/commit/7c93b74e8f3e69d6c88ef2891eb6accc99a6a1e8)) + + +### Performance Improvements + +* IconPicker新增搜索功能 ([a4d1391](https://github.com/kailong321200875/vue-element-plus-admin/commit/a4d1391390bb33d498f2ec2cc64965f1a0b0aaab)) +* useClipboard ([1db2248](https://github.com/kailong321200875/vue-element-plus-admin/commit/1db22482b43f6fb7ca8321b838fb41a5b0aff62e)) +* useNetwork ([88be3ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/88be3eea10196054596945af0eb9910e998dfd42)) +* 优化请求例子 ([6b3d2e1](https://github.com/kailong321200875/vue-element-plus-admin/commit/6b3d2e14985c1a7a3c68001e17820d0e7a833a56)) +* 完善demo ([2c4ff7d](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c4ff7d190c816a92d92f9c2dbe048436b2bf964)) +* 新增请求示例 ([2762aaf](https://github.com/kailong321200875/vue-element-plus-admin/commit/2762aaf09b3616944476797a6e112c350c12a0ec)) + +## [2.3.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.2.0...v2.3.0) (2023-09-24) + + +### Features + +* IconPicker ([4490d5e](https://github.com/kailong321200875/vue-element-plus-admin/commit/4490d5eeeb4389f94f90c9c45a30343324db2250)) +* 表格工具栏新增列设置功能 ([9d10ba8](https://github.com/kailong321200875/vue-element-plus-admin/commit/9d10ba821feca414b9b020322859ca4a47291005)) + + +### Bug Fixes + +* [#326](https://github.com/kailong321200875/vue-element-plus-admin/issues/326) ([c95a4e0](https://github.com/kailong321200875/vue-element-plus-admin/commit/c95a4e0763838e843cf5ce174110a01f2baa8000)) +* default interceptor response return ([c3d8540](https://github.com/kailong321200875/vue-element-plus-admin/commit/c3d8540ab284312f24d9355072f6fb4506ed6d1d)) +* 修复IconPicker BUG ([1e3aa78](https://github.com/kailong321200875/vue-element-plus-admin/commit/1e3aa789260773b1caecdaa32e1cafede22733e3)) +* 修复useCrudSchemas无法自定义label ([aa5deb1](https://github.com/kailong321200875/vue-element-plus-admin/commit/aa5deb13904e45e7cb6ec7285e936b9ebae57273)) + + +### Docs + +* 更新README ([4947c82](https://github.com/kailong321200875/vue-element-plus-admin/commit/4947c82d6770f0dce2845682f0c41d853268cf82)) +* 更新README ([c3624ce](https://github.com/kailong321200875/vue-element-plus-admin/commit/c3624cee588457e7fedaab360746500337c1b2a7)) +* 更新群二维码 ([ead1ab8](https://github.com/kailong321200875/vue-element-plus-admin/commit/ead1ab8c88c05593d539b56a811809382675faf5)) + + +### Styling + +* 修复样式层级问题 ([f92d2b6](https://github.com/kailong321200875/vue-element-plus-admin/commit/f92d2b60a956e1963b63e23b446a9d42096704e0)) +* 修改登录样式 ([bdd31f0](https://github.com/kailong321200875/vue-element-plus-admin/commit/bdd31f0621712af89d89b87ac439c3e0b398605a)) + +## [2.2.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.1.0...v2.2.0) (2023-08-27) + + +### Features + +* JsonEditor ([c0f4517](https://github.com/kailong321200875/vue-element-plus-admin/commit/c0f4517b87de5a0172a057fb9da141f758cca1fa)) +* 新增 useCrudSchemas demo ([ae0628e](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae0628e3af3466c7c9d7b593b825f776843de5ec)) +* 新增useTagsView ([a869a45](https://github.com/kailong321200875/vue-element-plus-admin/commit/a869a457e6a8052531ce3040ae0d332d7afbb478)) + + +### Bug Fixes + +* [#316](https://github.com/kailong321200875/vue-element-plus-admin/issues/316) ([7582e4d](https://github.com/kailong321200875/vue-element-plus-admin/commit/7582e4d12f18ae86f5ef4ff36211c364afca5763)) +* [#317](https://github.com/kailong321200875/vue-element-plus-admin/issues/317) ([2095caa](https://github.com/kailong321200875/vue-element-plus-admin/commit/2095caaa854b686b57f47ee183419f42563a5a95)) +* [#318](https://github.com/kailong321200875/vue-element-plus-admin/issues/318) ([4169e52](https://github.com/kailong321200875/vue-element-plus-admin/commit/4169e52baaaa43765848c29c5ce222d019e81c35)) +* [#319](https://github.com/kailong321200875/vue-element-plus-admin/issues/319) ([b6ee4e5](https://github.com/kailong321200875/vue-element-plus-admin/commit/b6ee4e5d48deb3a07f289366ed3700baa3674cd6)) +* 修复useValidator报错 ([4912f6c](https://github.com/kailong321200875/vue-element-plus-admin/commit/4912f6c0586249b3de7ac7d365c8ea98af7923c7)) +* 修复动态路由无效 ([1452a1a](https://github.com/kailong321200875/vue-element-plus-admin/commit/1452a1afc77eb3f64cd3de91a05ddc15e40f4a06)) + + +### Docs + +* 更新README ([5b4defa](https://github.com/kailong321200875/vue-element-plus-admin/commit/5b4defa8c4be2de894b2cb50ae9ea739a10cf7d9)) +* 更新群二维码 ([13aa71c](https://github.com/kailong321200875/vue-element-plus-admin/commit/13aa71c5bd5b5076599501961a24a171a9133c57)) +* 更新群二维码 ([ae29e97](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae29e974bfed2214d1beda703b976cdfa63070ab)) + + +### Styling + +* 修改Descriptions样式 ([cd0e05a](https://github.com/kailong321200875/vue-element-plus-admin/commit/cd0e05a6b9146af7ae64be62613724cd58e6c2a3)) + + +### Code Refactoring + +* 重构useValidator ([b8849da](https://github.com/kailong321200875/vue-element-plus-admin/commit/b8849dabe2b306831f69e84db167a367570d992a)) + + +### Performance Improvements + +* 优化动态路由 ([8793588](https://github.com/kailong321200875/vue-element-plus-admin/commit/879358821d02d5e4575dfee0d189b9fee7f2e217)) +* 完善useTagsView ([e0c55f4](https://github.com/kailong321200875/vue-element-plus-admin/commit/e0c55f40d4c1c47e29de6c4c7e9433efa978bf7f)) +* 完善useTagsView ([175abd0](https://github.com/kailong321200875/vue-element-plus-admin/commit/175abd0aa3388e8473f6ecbf63e28133fce55bd3)) +* 更新demo ([2c99cd2](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c99cd20f0c25a740ac7a3a8319f7a112e69c0d3)) + +## [2.1.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v2.0.0...v2.1.0) (2023-08-12) + + +### Features + +* 新增多开标签页Demo ([5c253ce](https://github.com/kailong321200875/vue-element-plus-admin/commit/5c253ce803a9ef7ce03534ddd5f0865db4602378)) + + +### Bug Fixes + +* [#307](https://github.com/kailong321200875/vue-element-plus-admin/issues/307) ([4ce07e1](https://github.com/kailong321200875/vue-element-plus-admin/commit/4ce07e150c0bd3903cc5f43fcd88c2cb292d7690)) +* [#311](https://github.com/kailong321200875/vue-element-plus-admin/issues/311) ([bdde4cc](https://github.com/kailong321200875/vue-element-plus-admin/commit/bdde4ccd39d5d698d68b299c6e80546d4a8be89f)) +* 修复eslint错误 ([b5e47e0](https://github.com/kailong321200875/vue-element-plus-admin/commit/b5e47e04d8f5f889e0c46a2dced108d058ded94e)) +* 修复Table插槽传参错误 ([97344e6](https://github.com/kailong321200875/vue-element-plus-admin/commit/97344e68f5abb144d9e5d4ad273108858dbcfba2)) +* 修复Table组件插槽传参错误 ([c83a026](https://github.com/kailong321200875/vue-element-plus-admin/commit/c83a026d559e2854fead17d2e28fbebcf25490de)) + + +### Docs + +* 修改Readme ([ee059b7](https://github.com/kailong321200875/vue-element-plus-admin/commit/ee059b7619ad01ded9d3be20287086ddbcce3253)) +* 修改Readme ([e05f5a7](https://github.com/kailong321200875/vue-element-plus-admin/commit/e05f5a77edc175daa267e4fc6abbcfc8fec2e291)) +* 修改Readme ([b0e561d](https://github.com/kailong321200875/vue-element-plus-admin/commit/b0e561d8acd36e8780087e317cc34257956981fd)) +* 修改Readme ([fced2e0](https://github.com/kailong321200875/vue-element-plus-admin/commit/fced2e0087694445a89cf360e5e3e3013d8ca604)) +* 修改README ([dce76f0](https://github.com/kailong321200875/vue-element-plus-admin/commit/dce76f042d5243039540828a3fd982af25f37531)) +* 更新群二维码 ([607ef58](https://github.com/kailong321200875/vue-element-plus-admin/commit/607ef585d010c9ade6f54d96c2a12b36099ece74)) + + +### Styling + +* 修改TabMenu样式 ([e8cd6f9](https://github.com/kailong321200875/vue-element-plus-admin/commit/e8cd6f9e1c4387c582e461cde4d59796bf17c1bd)) + +## [2.0.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.10.0...v2.0.0) (2023-08-06) + + +### ⚠ BREAKING CHANGES + +* 重构完成 + +### Features + +* 重构完成 ([76e971e](https://github.com/kailong321200875/vue-element-plus-admin/commit/76e971ef96ad4f5cc7df58abd0559898ce70207d)) + + +### Code Refactoring + +* 重构完成 ([85f8cda](https://github.com/kailong321200875/vue-element-plus-admin/commit/85f8cda19d8cafb951f211b845aad970a661dd1e)) +* 重构完成 ([5d55597](https://github.com/kailong321200875/vue-element-plus-admin/commit/5d55597cca6c9d2bc6cb6211a01c161fa5f086ba)) + +## [1.10.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.9...v1.10.0) (2023-08-06) + + +### Types + +* Form类型调整 ([a0f4aeb](https://github.com/kailong321200875/vue-element-plus-admin/commit/a0f4aebc5a685366cd56b1a7bb39fa614976e3bb)) +* Form类型调整 ([674d760](https://github.com/kailong321200875/vue-element-plus-admin/commit/674d760029b451c0c6fc23a2aeac5c83992a0b27)) +* 修改类型 ([c3ac191](https://github.com/kailong321200875/vue-element-plus-admin/commit/c3ac1915045d4d59bca09ec6d19151bc5da342f1)) +* 修改类型 ([7d0476f](https://github.com/kailong321200875/vue-element-plus-admin/commit/7d0476f47c5858019db871cff2bdd19f0210f0d4)) +* 类型优化 ([283bc58](https://github.com/kailong321200875/vue-element-plus-admin/commit/283bc58d46151a8954bb81ee6bf8f499177b15fc)) +* 调整类型 ([24c8af9](https://github.com/kailong321200875/vue-element-plus-admin/commit/24c8af91835fb2c8c00e7c2673fff01f098c9944)) +* 迁移types ([ccbec86](https://github.com/kailong321200875/vue-element-plus-admin/commit/ccbec865568b1c9b3c3321d7071c164fdc350a0f)) +* 迁移types ([46b35e4](https://github.com/kailong321200875/vue-element-plus-admin/commit/46b35e48b3e7876c74159625b5149ef663396f5c)) + + +### Features + +* axios 改造 ([3238140](https://github.com/kailong321200875/vue-element-plus-admin/commit/32381408bbe418eeaca2a975305bac80ddaa03f5)) +* axios 改造 ([5807db1](https://github.com/kailong321200875/vue-element-plus-admin/commit/5807db1dc12a7ff2dbf66801a742a78974ad8f9c)) +* Descriptions组件重构 ([49e415d](https://github.com/kailong321200875/vue-element-plus-admin/commit/49e415d27788cb468c96f2a828f1df7ae65b7a3c)) +* Dialog组件重构 ([3701a04](https://github.com/kailong321200875/vue-element-plus-admin/commit/3701a04231af02ec7f7ef73533f3a22e707380fb)) +* Form useForm 完成 ([3e4e27c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3e4e27c21fd59c944229856bee929f005d2ee140)) +* Form改造 ([9c724dc](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c724dc9aad18397d5ecd00e53c3c24e142a34b5)) +* Icon改版 ([882f162](https://github.com/kailong321200875/vue-element-plus-admin/commit/882f162ff21c74239b638f284f52161e5791722d)) +* Radio改造 ([deeee73](https://github.com/kailong321200875/vue-element-plus-admin/commit/deeee73bcb3ad912844fddee62b1155d95d4b42b)) +* Radio改造 ([83513d5](https://github.com/kailong321200875/vue-element-plus-admin/commit/83513d519d4b6b8fbfd48db266b9bd7b3a998d63)) +* Search组件重构 ([a7f3702](https://github.com/kailong321200875/vue-element-plus-admin/commit/a7f370214481577ab82bf2871191dda717c7978a)) +* SelectV2改造完成 ([4d04734](https://github.com/kailong321200875/vue-element-plus-admin/commit/4d04734e13f6926c16aeee421feecb0d339534f0)) +* Table重构 ([94800b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/94800b0120ee05ca7d534dda3e59653f38d7fda0)) +* 完善search组件demo ([cdf44a4](https://github.com/kailong321200875/vue-element-plus-admin/commit/cdf44a43a05010dbcba3a3ec0cb7c8251f16fce3)) +* 拖拽表格 ([b69b8ed](https://github.com/kailong321200875/vue-element-plus-admin/commit/b69b8ed1bde36100fc86e51fcc63805d4ea21210)) +* 新增TreeSelect表单项 ([de0cb43](https://github.com/kailong321200875/vue-element-plus-admin/commit/de0cb43566b9065250abbc71548ffeca4c8e8bf1)) +* 新增Uload ([c181887](https://github.com/kailong321200875/vue-element-plus-admin/commit/c181887f7f0c5eecc9584edfe99e9065440bdc56)) +* 新增useStorage ([dfea91c](https://github.com/kailong321200875/vue-element-plus-admin/commit/dfea91c7e1d18fa299067c62557cac61723ea861)) +* 新增权限测试页 ([3fe40ba](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fe40ba62df29c2ffea9adfd65fc559489481e24)) +* 新增锁屏功能 ([e2fd349](https://github.com/kailong321200875/vue-element-plus-admin/commit/e2fd349070147c57f9400fa9a413260b7707bda2)) +* 用户列表重构 ([755cea0](https://github.com/kailong321200875/vue-element-plus-admin/commit/755cea0990d9e3b64c936f29c02e4053393a1a19)) +* 登录页改造 ([5312951](https://github.com/kailong321200875/vue-element-plus-admin/commit/5312951359b5d919b6c1a03783aa6bbaf8ec0044)) +* 综合示例重构 ([9a0259d](https://github.com/kailong321200875/vue-element-plus-admin/commit/9a0259de5c47970502db95f4dda24998ad5d9efe)) +* 菜单管理 ([c72b3a3](https://github.com/kailong321200875/vue-element-plus-admin/commit/c72b3a33aab7d3605770a64d23b8a84ef4ad68d2)) +* 角色管理 ([47016a5](https://github.com/kailong321200875/vue-element-plus-admin/commit/47016a535f2b7a22ab498bee197bc30a983f507d)) +* 部门管理 ([28d0785](https://github.com/kailong321200875/vue-element-plus-admin/commit/28d0785be842022cae7808c23e1f19eaab5fb996)) +* 重构Dialog组件示例 ([9a78ac9](https://github.com/kailong321200875/vue-element-plus-admin/commit/9a78ac977eb0cfb3bd6c2a9b96e69d9f010017f4)) + + +### Bug Fixes + +* mock数据 ([8bdac71](https://github.com/kailong321200875/vue-element-plus-admin/commit/8bdac7152f463cd98c50c9893a46bb6c111fd428)) +* 修复Form已知问题 ([097b32e](https://github.com/kailong321200875/vue-element-plus-admin/commit/097b32e1a9d92a609a66179d68b3dabe12f96b66)) +* 修复Table组件已知问题 ([b1a83f6](https://github.com/kailong321200875/vue-element-plus-admin/commit/b1a83f601838cb82fb29c036654a4cdc729997cd)) +* 修复类型错误 ([26dc886](https://github.com/kailong321200875/vue-element-plus-admin/commit/26dc886f8ccb5cf1ffc10e1d9601c827a1f960c2)) +* 样式问题修复 ([cdc7c76](https://github.com/kailong321200875/vue-element-plus-admin/commit/cdc7c76eb5ac3ccb79f5f55ff5b7ce6b8c4955e1)) +* 解决类型检测报错 ([9d93496](https://github.com/kailong321200875/vue-element-plus-admin/commit/9d9349600b3d2008e4216d49c9fa1c1b9995fa79)) +* 解决类型检测报错 ([513108c](https://github.com/kailong321200875/vue-element-plus-admin/commit/513108c00e622812e2e70dfe833435f6b5462d6e)) +* 解决类型检测报错 ([28bf8be](https://github.com/kailong321200875/vue-element-plus-admin/commit/28bf8bee45e3cc8575a356623abdbe56e30991f8)) + + +### Styling + +* Table样式修改 ([5fc57bd](https://github.com/kailong321200875/vue-element-plus-admin/commit/5fc57bdb08488f6898eafd6f28289b0567d6d9e2)) +* Table样式修改 ([411c0f7](https://github.com/kailong321200875/vue-element-plus-admin/commit/411c0f792ae8359c49e81974d8193f049120985b)) +* Table样式修改 ([d487c6a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d487c6a93ec0281d76a3938e6e23ea2a4a7940c1)) +* Table样式修改 ([c7d21e3](https://github.com/kailong321200875/vue-element-plus-admin/commit/c7d21e36d012377ba863ac848d77abb5db4f475a)) +* Table样式修改 ([7f5078a](https://github.com/kailong321200875/vue-element-plus-admin/commit/7f5078a436c4d5abcaf7a420df35d2be9b3680c5)) +* 修改Dialog样式 ([e451bfc](https://github.com/kailong321200875/vue-element-plus-admin/commit/e451bfcde6e5a47d4b3022e240ffcc0576ebb9a8)) +* 修改样式 ([207c5b3](https://github.com/kailong321200875/vue-element-plus-admin/commit/207c5b3fc4e52bb06baa36cd4b659e14893785ba)) +* 完善角色管理 ([c4576bd](https://github.com/kailong321200875/vue-element-plus-admin/commit/c4576bd57bcf504733f20188202ea7d33ab1c184)) +* 布局样式优化 ([962689a](https://github.com/kailong321200875/vue-element-plus-admin/commit/962689a8bd0ed5eb17d946b8a21dec4a197f13a7)) +* 样式布局调整完成 ([7193176](https://github.com/kailong321200875/vue-element-plus-admin/commit/719317694f71e22692256bb557070343f034ffe5)) +* 用户管理样式修改 ([57a5fa7](https://github.com/kailong321200875/vue-element-plus-admin/commit/57a5fa7b82ae9f3d7a1f8ec5391f14b1d1cd32e8)) +* 移除不必要样式 ([7ef1d1e](https://github.com/kailong321200875/vue-element-plus-admin/commit/7ef1d1e3013cc5bf7fc574e67c2004f50792e66d)) +* 移除不必要样式 ([366db45](https://github.com/kailong321200875/vue-element-plus-admin/commit/366db4528254d18659e6a922817702b5b92a57b0)) +* 调整Icon悬停样式 ([64c7e48](https://github.com/kailong321200875/vue-element-plus-admin/commit/64c7e48bd18ba83e605daccbc4c2f4cc6b58695d)) +* 调整工作台样式错乱 ([cc18f29](https://github.com/kailong321200875/vue-element-plus-admin/commit/cc18f297ef50655d5773d01fcfddabc365dc53e7)) + + +### Performance Improvements + +* Dialog默认高度修改 ([0e04fce](https://github.com/kailong321200875/vue-element-plus-admin/commit/0e04fce4367d6829e8de97a249318b0309e06fd5)) +* Form Table Search Descriptions 支持嵌套赋值 ([46ddf62](https://github.com/kailong321200875/vue-element-plus-admin/commit/46ddf62d2d4ce1a653f47695cb0bb3475aa16bd8)) +* ImageViewer组件优化 ([3b9c3d8](https://github.com/kailong321200875/vue-element-plus-admin/commit/3b9c3d8b757646eaf74625403112a969bfd15e55)) +* 优化Form事件传递 ([69cafb3](https://github.com/kailong321200875/vue-element-plus-admin/commit/69cafb3b7b2ce7ecbd9f2e8ef09e250817e9a55c)) +* 优化Search组件 ([e548668](https://github.com/kailong321200875/vue-element-plus-admin/commit/e548668ccef8c41d9ac7d9fe39ffe66471d160d2)) +* 优化表单组件 ([77a3866](https://github.com/kailong321200875/vue-element-plus-admin/commit/77a38662488ab9ff4cbe5ff3cf9b65eea34abca1)) +* 优化锁屏组件 ([4f8330a](https://github.com/kailong321200875/vue-element-plus-admin/commit/4f8330a4faf6cc98a9bac17bd3e1719ae1b30c81)) + +## [1.9.9](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.8...v1.9.9) (2023-04-13) + + +### Bug Fixes + +* 使用动态路由时,多级路由只有一个子路且父路由未使用alwaysShow时,子路由未添加至路由中 ([9b330a1](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b330a1f513d3af9233b9a9dde6bdfeeefbc3393)) + +## [1.9.8](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.7...v1.9.8) (2023-04-12) + + +### Bug Fixes + +* 修复已知问题 ([0a6f306](https://github.com/kailong321200875/vue-element-plus-admin/commit/0a6f306686ea024e30bcdccac34e485b8526e38f)) + +## [1.9.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.6...v1.9.7) (2023-03-28) + + +### Bug Fixes + +* 修复表格与搜索框字段不能不一致的问题 ([5c1cd29](https://github.com/kailong321200875/vue-element-plus-admin/commit/5c1cd298defefb36b858adc766b776a0a7b9bd66)) + +## [1.9.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.5...v1.9.6) (2023-03-22) + + +### Bug Fixes + +* 修改 Editor 的 z-index 使其不会遮挡『综合示例 - 新增』界面的下拉菜单 ([c046e45](https://github.com/kailong321200875/vue-element-plus-admin/commit/c046e4554ba8fd99614484d8fb636650072b833e)) + +## [1.9.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.4...v1.9.5) (2023-03-13) + + +### Bug Fixes + +* 面包屑:1.修复使用动态路由的时候,无法显示的bug ([8790c8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/8790c8cbd8d63ea0f8f276fd5af006f39b06e7d3)) + +## [1.9.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.3...v1.9.4) (2023-03-03) + + +### Bug Fixes + +* 修复已知BUG ([782b8e2](https://github.com/kailong321200875/vue-element-plus-admin/commit/782b8e2f94c867c3ee282287c37c888fff93fc55)) + +## [1.9.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.2...v1.9.3) (2023-03-01) + + +### Types + +* 修复类型错误 ([297b2c6](https://github.com/kailong321200875/vue-element-plus-admin/commit/297b2c69a239b487126c3b9316645a1b5f06bb7c)) + + +### Styling + +* 抽屉弹出样式问题 ([16a3eef](https://github.com/kailong321200875/vue-element-plus-admin/commit/16a3eef85a1ffb296bd44f67d89a911ecaf1c25e)) +* 调整主题切换样式 ([6e6beef](https://github.com/kailong321200875/vue-element-plus-admin/commit/6e6beefc3c380f7297985adcabcf966fbd2c5197)) + +## [1.9.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.1...v1.9.2) (2023-01-16) + + +### Bug Fixes + +* 修复TS类型错误 ([1c06a27](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c06a27b900a891cd0b47098062cebc984ff6505)) + +## [1.9.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.0...v1.9.1) (2023-01-11) + + +### Bug Fixes + +* dark mode toggle ([bbc7646](https://github.com/kailong321200875/vue-element-plus-admin/commit/bbc764601ec864c2fdbe3ad78c083c5ae80615e0)) + +## [1.9.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.7...v1.9.0) (2022-12-28) + + +### Features + +* 添加打包进度条 ([354e87f](https://github.com/kailong321200875/vue-element-plus-admin/commit/354e87f7c533ad8e93ef484b47d0fe16f17048c9)) + + +### Bug Fixes + +* husky ([6fe5b2e](https://github.com/kailong321200875/vue-element-plus-admin/commit/6fe5b2e6c781b251bff5f0ac936c04dcfe5ef95f)) + +## [1.8.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.6...v1.8.7) (2022-12-05) + + +### Bug Fixes + +* 解决iframe无法正常工作 ([4fcc46f](https://github.com/kailong321200875/vue-element-plus-admin/commit/4fcc46fccf747b47909e2079c4f2abc5dbfb1a0c)) + +## [1.8.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.5...v1.8.6) (2022-11-21) + + +### Bug Fixes + +* 修复Search组件无法默认值 ([3368fda](https://github.com/kailong321200875/vue-element-plus-admin/commit/3368fda251bd3ff5a8e0059b3b33f9c0339d236b)) + +## [1.8.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.4...v1.8.5) (2022-11-17) + + +### Bug Fixes + +* 修复Form赋值问题 ([f37cc1b](https://github.com/kailong321200875/vue-element-plus-admin/commit/f37cc1b5801add3ada168dbbcf4cd2c340f0e30d)) + +## [1.8.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.3...v1.8.4) (2022-11-07) + + +### Bug Fixes + +* 修复option禁用属性无效 ([0b671e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b671e914e396c7666ad5e34768a6e29f7dfbd33)) + + +### Styling + +* input默认宽度与select对齐 ([0b671e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b671e914e396c7666ad5e34768a6e29f7dfbd33)) + +## [1.8.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.2...v1.8.3) (2022-10-28) + + +### Performance Improvements + +* 优化描述组件 ([73ecc98](https://github.com/kailong321200875/vue-element-plus-admin/commit/73ecc98671d430013920246d98ce9ab1752e56eb)) + +## [1.8.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.1...v1.8.2) (2022-10-18) + + +### Bug Fixes + +* Correct spelling of words(aciton →action) ([eb405b2](https://github.com/kailong321200875/vue-element-plus-admin/commit/eb405b2a9041ca0ad4455db79bf617ec910dc485)) +* Correct spelling of words(tigger →trigger) ([c2ca2d7](https://github.com/kailong321200875/vue-element-plus-admin/commit/c2ca2d736c92e02380923a6741450844acb41a38)) + +## [1.8.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.0...v1.8.1) (2022-10-11) + + +### Bug Fixes + +* 修复cutMenu收起时 ([993af6b](https://github.com/kailong321200875/vue-element-plus-admin/commit/993af6bb6576249e66e0c0ea592ebf851f65ab8c)) + + +### Styling + +* cutMenu层级样式 ([32d2408](https://github.com/kailong321200875/vue-element-plus-admin/commit/32d2408588c487cff2cf73e3cc132e5105ff4459)) + +## [1.8.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.7.1...v1.8.0) (2022-10-10) + + +### Features + +* types优化 ([3351155](https://github.com/kailong321200875/vue-element-plus-admin/commit/33511553cd9055b036b2d7491f9c2eda123f8b22)) + + +### Styling + +* 优化第四种布局 ([122fa62](https://github.com/kailong321200875/vue-element-plus-admin/commit/122fa62d859413d16175e0d97c7bf13f232dbb3a)) + +## [1.7.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.7.0...v1.7.1) (2022-10-10) + + +### Bug Fixes + +* 修正types提示错误 ([ef3e006](https://github.com/kailong321200875/vue-element-plus-admin/commit/ef3e006859dcd8b93ffb7cffcaeae24cbb330f2a)) + +## [1.7.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.6...v1.7.0) (2022-10-09) + + +### Features + +* type抽离 ([8b4fa1a](https://github.com/kailong321200875/vue-element-plus-admin/commit/8b4fa1aa21aa2c1379288315ccd64a6f3375be51)) + +## [1.6.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.5...v1.6.6) (2022-10-09) + + +### Bug Fixes + +* table search params ([a62929a](https://github.com/kailong321200875/vue-element-plus-admin/commit/a62929a8dac21028d3dd1cddf98189492c33b093)) + +## [1.6.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.4...v1.6.5) (2022-10-08) + + +### Bug Fixes + +* The attribute of option does not work ([d946920](https://github.com/kailong321200875/vue-element-plus-admin/commit/d946920e61ed81beacf9f1f8be7ee1f50505f64d)) + + +### Performance Improvements + +* perf store ([d416178](https://github.com/kailong321200875/vue-element-plus-admin/commit/d416178d69ca6100be4b635922b1a22d27629f08)) +* token test ([b320e65](https://github.com/kailong321200875/vue-element-plus-admin/commit/b320e658d1a559a6eaebdf374d63649c223c2ecd)) + +## [1.6.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.3...v1.6.4) (2022-09-21) + + +### Bug Fixes + +* fix bug ([da39f3b](https://github.com/kailong321200875/vue-element-plus-admin/commit/da39f3bc904ca2d80f432a31709725f9a57deb19)) + +## [1.6.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.2...v1.6.3) (2022-08-20) + + +### Bug Fixes + +* 修复重定向错误 ([89d03fd](https://github.com/kailong321200875/vue-element-plus-admin/commit/89d03fd067e7aca565ceb84ea9276f340bbfcb60)) + + +### Styling + +* 调整样式 ([d29e151](https://github.com/kailong321200875/vue-element-plus-admin/commit/d29e151f8a660031a685f6ef9f789532b1b7b58b)) + +## [1.6.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.1...v1.6.2) (2022-08-13) + + +### Styling + +* Misspelling ([c43e833](https://github.com/kailong321200875/vue-element-plus-admin/commit/c43e833582e4f14ac78b0683f1eb3bdeb9fb4821)) +* perfect tableDemo ([c589edd](https://github.com/kailong321200875/vue-element-plus-admin/commit/c589edd960b23ad0c8b56d2c7880b61014114d45)) + + +### Code Refactoring + +* refactor axios ([0980640](https://github.com/kailong321200875/vue-element-plus-admin/commit/0980640f65fc80e3e58ba49e98db10b7b1b80077)) + +## [1.6.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.6.0...v1.6.1) (2022-07-30) + + +### Bug Fixes + +* fix menu active bug ([ff59fc7](https://github.com/kailong321200875/vue-element-plus-admin/commit/ff59fc7e133202945360a7e210f9cdf3a4a89dd7)) +* Pie chart data not updated ([55d4ce7](https://github.com/kailong321200875/vue-element-plus-admin/commit/55d4ce7e35ff9a0c5590bc3589160cfd304d3ae5)) + + +### Performance Improvements + +* add static router ([55522b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/55522b0661a8df3ad3c8afafcc9f8fcb162c5a00)) + + +### Styling + +* tagviews styles update ([bff7d93](https://github.com/kailong321200875/vue-element-plus-admin/commit/bff7d9370db7a9c171828721bb99643dac2f235d)) + +## [1.6.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.4...v1.6.0) (2022-07-18) + + +### Features + +* 添加按钮权限 ([7bef662](https://github.com/kailong321200875/vue-element-plus-admin/commit/7bef662db1e91aa8164e9f7a92de3fe4480a3c3b)) + + +### Performance Improvements + +* 移除md5依赖 ([a123097](https://github.com/kailong321200875/vue-element-plus-admin/commit/a123097f1f38eac45e945c7d3fdccafc16ea9b69)) + + +### Styling + +* 压缩图片尺寸 ([ae3c565](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae3c5657b604ffbdae5ce3ce3603626ad4acc5e5)) + + +### Docs + +* vite2 to vite3 ([b3918b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/b3918b9c3c5de4b48811ec95967851cfb3c231e1)) +* vite2 to vite3 ([aaf07de](https://github.com/kailong321200875/vue-element-plus-admin/commit/aaf07de77aa600332880a894faa35757f787c012)) + +## [1.6.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.4...v1.6.0) (2022-07-18) + + +### Features + +* 添加按钮权限 ([7bef662](https://github.com/kailong321200875/vue-element-plus-admin/commit/7bef662db1e91aa8164e9f7a92de3fe4480a3c3b)) + + +### Performance Improvements + +* 移除md5依赖 ([a123097](https://github.com/kailong321200875/vue-element-plus-admin/commit/a123097f1f38eac45e945c7d3fdccafc16ea9b69)) + + +### Styling + +* 压缩图片尺寸 ([ae3c565](https://github.com/kailong321200875/vue-element-plus-admin/commit/ae3c5657b604ffbdae5ce3ce3603626ad4acc5e5)) + + +### Docs + +* vite2 to vite3 ([b3918b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/b3918b9c3c5de4b48811ec95967851cfb3c231e1)) +* vite2 to vite3 ([aaf07de](https://github.com/kailong321200875/vue-element-plus-admin/commit/aaf07de77aa600332880a894faa35757f787c012)) + +## [1.5.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.3...v1.5.4) (2022-07-16) + + +### Bug Fixes + +* fix build:test error ([14530cf](https://github.com/kailong321200875/vue-element-plus-admin/commit/14530cf790bfbbe37c72fa831f0376bbb4209e9d)) + +## [1.5.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.2...v1.5.3) (2022-07-01) + + +### Bug Fixes + +* fix useCrudSchemas not work ([0a855b9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0a855b93e282dfe7863b3fce31dde5d7e0d3e2b6)) + +## [1.5.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.1...v1.5.2) (2022-07-01) + + +### Performance Improvements + +* add useCrudSchemas demo ([ca3ce54](https://github.com/kailong321200875/vue-element-plus-admin/commit/ca3ce54630b723d87415b14c642440d6734876ff)) + +## [1.5.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.5.0...v1.5.1) (2022-07-01) + + +### Bug Fixes + +* change showMainRoute to canTo ([5e292f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/5e292f8a2b2ded7297a2a76893e113ac81517d23)) + + +### Performance Improvements + +* dialog combine with form ([34aefb6](https://github.com/kailong321200875/vue-element-plus-admin/commit/34aefb64ab9237521a1225925264818eebff9ad3)) +* dynamic options demo ([1acb4d7](https://github.com/kailong321200875/vue-element-plus-admin/commit/1acb4d7e8f449ba342699f1b4387ac2404a4c1fb)) +* dynamic options demo ([9a3b617](https://github.com/kailong321200875/vue-element-plus-admin/commit/9a3b6177aa0fbc99c86c5073a1c6c696e1eaf890)) +* useCrudSchemas cutom label ([7864d83](https://github.com/kailong321200875/vue-element-plus-admin/commit/7864d830e2134d814609e722b7bad1754ea9460e)) + +## [1.5.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.5...v1.5.0) (2022-06-25) + + +### Features + +* refactoring API ([37b7583](https://github.com/kailong321200875/vue-element-plus-admin/commit/37b75839a591648b145065432efb1dc8c7a3b917)) + + +### Bug Fixes + +* 修复axios已知问题 ([537af57](https://github.com/kailong321200875/vue-element-plus-admin/commit/537af57a0aaa24c88ebe75acf52dc0403a58b04b)) + + +### Performance Improvements + +* perf axios config ([39edd84](https://github.com/kailong321200875/vue-element-plus-admin/commit/39edd84023109a84683c21ea33e41bd024756520)) + +## [1.4.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.4...v1.4.5) (2022-06-09) + + +### Bug Fixes + +* fix tagsview not work ([d88e051](https://github.com/kailong321200875/vue-element-plus-admin/commit/d88e0514349e877f1c5280a48f9b1bd2bfd622bf)) +* fix tagsview not work ([1bf2d4c](https://github.com/kailong321200875/vue-element-plus-admin/commit/1bf2d4c77287fdca7ed1cb8c9998a53f1375dc6f)) + + +### Types + +* fix types error ([586486a](https://github.com/kailong321200875/vue-element-plus-admin/commit/586486a68d4bf2a024e50a79945b4007324f642d)) + +## [1.4.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.3...v1.4.4) (2022-06-06) + + +### Types + +* fix type error ([d66f12e](https://github.com/kailong321200875/vue-element-plus-admin/commit/d66f12e0e77f6acf485bae06509d9ea4abcd1eaa)) + +### [1.4.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.2...v1.4.3) (2022-06-01) + + +### Bug Fixes + +* multiple requests when pageSize change and currentPage isn't 1 ([f71a250](https://github.com/kailong321200875/vue-element-plus-admin/commit/f71a2503bc521c01e7102feecf4ec39a5224a6bb)) + +### [1.4.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.1...v1.4.2) (2022-05-15) + + +### Styling + +* fix dark mode bug ([2f9fd5d](https://github.com/kailong321200875/vue-element-plus-admin/commit/2f9fd5d21550d771ec12ae3540b975e2eebcd25b)) + +### [1.4.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.4.0...v1.4.1) (2022-05-12) + + +### Bug Fixes + +* the warning of VSCode extensions ([a368c21](https://github.com/kailong321200875/vue-element-plus-admin/commit/a368c21fb9c41f98f31f51586a2023076a8a9132)) + +## [1.4.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.2...v1.4.0) (2022-05-10) + + +### Features + +* add dark mode ([0758a6a](https://github.com/kailong321200875/vue-element-plus-admin/commit/0758a6a9d83170e53d45d39c3313e52ff5885746)) + +### [1.3.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.1...v1.3.2) (2022-05-07) + + +### Bug Fixes + +* fix the problem that the page is stuck in top mode ([8d01f48](https://github.com/kailong321200875/vue-element-plus-admin/commit/8d01f48d5098195b10c03b3cb3a0f485ebc9e018)) + +### [1.3.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.3.0...v1.3.1) (2022-05-06) + + +### Bug Fixes + +* spelling 'useRenderChcekbox' ([ee92f03](https://github.com/kailong321200875/vue-element-plus-admin/commit/ee92f039bea4307ccfb819728d3e2ed04fa00e03)) + +## [1.3.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.13...v1.3.0) (2022-04-26) + + +### Features + +* add useCrudSchemas hook ([00d947e](https://github.com/kailong321200875/vue-element-plus-admin/commit/00d947e2f81105194b0622d33768f999e37ad28a)) + + +### Bug Fixes + +* fix Table slot warning ([0eac05d](https://github.com/kailong321200875/vue-element-plus-admin/commit/0eac05d4f973ff7b15e00973f6e96595a3cd6d43)) + + +### Code Refactoring + +* refactor useAxios ([185f1e6](https://github.com/kailong321200875/vue-element-plus-admin/commit/185f1e6e210ecaac28ebfdee4198b7ca2eaa0933)) + + +### Build System + +* add url ([ab0f59a](https://github.com/kailong321200875/vue-element-plus-admin/commit/ab0f59ac91a077cf060923fa76e6d57e05d0b21b)) +* update plugins ([c475a61](https://github.com/kailong321200875/vue-element-plus-admin/commit/c475a610c19094034306f2dc665e240c7c117f87)) +* update plugins ([dfedbc7](https://github.com/kailong321200875/vue-element-plus-admin/commit/dfedbc74fdb2c819a96b6263849bdaab59b9e337)) + +### [1.2.13](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.12...v1.2.13) (2022-04-18) + + +### Performance Improvements + +* Editor component support v-model ([d77f8e3](https://github.com/kailong321200875/vue-element-plus-admin/commit/d77f8e334d77ee43c9ee0f411733f7397b278bc0)) + +### [1.2.12](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.11...v1.2.12) (2022-04-17) + + +### Bug Fixes + +* fixed spelling 'ElememtPlusSzie' ([5dbbc60](https://github.com/kailong321200875/vue-element-plus-admin/commit/5dbbc608640d93fe68fec6f58fdb30a43e02aada)) + +### [1.2.11](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.10...v1.2.11) (2022-04-14) + + +### Bug Fixes + +* fix the error reported by the Editor component ([7dc6d8a](https://github.com/kailong321200875/vue-element-plus-admin/commit/7dc6d8a9d7289bfaf27f972e9ca1773c0a1ddd7d)) +* fix the error reported by the Editor component ([90ef985](https://github.com/kailong321200875/vue-element-plus-admin/commit/90ef9856a0885fa812339cb7047ecc98b86c7b73)) + + +### Performance Improvements + +* add tagsViewIcon setting ([d395f03](https://github.com/kailong321200875/vue-element-plus-admin/commit/d395f03a57a9265f1d39b3220fc7c9b983efee30)) +* add uniqueopened setting ([b060319](https://github.com/kailong321200875/vue-element-plus-admin/commit/b0603199a5ae0ee923483dad449f49220d36f444)) + + +### Build System + +* update plugins ([2ee4954](https://github.com/kailong321200875/vue-element-plus-admin/commit/2ee49549e7b601af26ef5204f7648d271f3348f2)) + + +### Styling + +* add layout background color ([9b614fe](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b614fe89288538197c50f164586aeed7836b7a8)) + +### [1.2.10](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.9...v1.2.10) (2022-04-12) + + +### Bug Fixes + +* fix bug ([327522f](https://github.com/kailong321200875/vue-element-plus-admin/commit/327522f2b73ae0e11f8ebbc39394b06029ce0b65)) + + +### Styling + +* modify the commitlint package manager ([ba7e722](https://github.com/kailong321200875/vue-element-plus-admin/commit/ba7e7224ab58612548519415f5429c32827a61de)) + +### [1.2.9](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.8...v1.2.9) (2022-04-12) + + +### Docs + +* update changlog ([e37273d](https://github.com/kailong321200875/vue-element-plus-admin/commit/e37273d95d29a3bb752604658d550264aacdc979)) + +### [1.2.8](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.7...v1.2.8) (2022-04-11) + +### Build System + +- update plugins ([00a573a](https://github.com/kailong321200875/vue-element-plus-admin/commit/00a573af3f455395b4ee2ab99a03f3103d466e9c)) + +### Docs + +- update changlog ([62fc183](https://github.com/kailong321200875/vue-element-plus-admin/commit/62fc1839fdff3a4d06a7db4cf3f8ce2cb9aee681)) + +### [1.2.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.6...v1.2.7) (2022-04-10) + +### Build System + +- update plugins ([f13a91d](https://github.com/kailong321200875/vue-element-plus-admin/commit/f13a91dd460b1dcdbd17aef723ab3ca2b01c34f0)) + +### Styling + +- .bhs code formatting ([57b2707](https://github.com/kailong321200875/vue-element-plus-admin/commit/57b27071e9a33423c46542a5d0e5d5c2e9a3b718)) + +### [1.2.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.5...v1.2.6) (2022-04-08) + +### Build System + +- update plugins ([d645892](https://github.com/kailong321200875/vue-element-plus-admin/commit/d645892cde2f7f43215a2ba1776ee94a322437bf)) + +### [1.2.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.4...v1.2.5) (2022-04-08) + +### Performance Improvements + +- add plop ([fa54a17](https://github.com/kailong321200875/vue-element-plus-admin/commit/fa54a1704ffd93f7b42dbeb1229bc4868d2d3a6a)) + +### Build System + +- update plugins ([18c6bd8](https://github.com/kailong321200875/vue-element-plus-admin/commit/18c6bd868622d954b51ea34e37516361ad4eb540)) + +### Styling + +- fix padding and background color ([f8c9d54](https://github.com/kailong321200875/vue-element-plus-admin/commit/f8c9d54687edafd92f5b61bf5288bb1188c73f01)) + +### [1.2.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.3...v1.2.4) (2022-04-06) + +### Bug Fixes + +- add Sticky props comment ([46133b3](https://github.com/kailong321200875/vue-element-plus-admin/commit/46133b3ff39d48d11cbcaa1f20a271118f48eb29)) +- fix bug ([179ca06](https://github.com/kailong321200875/vue-element-plus-admin/commit/179ca064ba8adbb3b063d9798ec1930ccc68e459)) +- fix remove unnecessary variables ([ca01cbf](https://github.com/kailong321200875/vue-element-plus-admin/commit/ca01cbfd98b63a0d76190fe8d43097fdc9df74e6)) +- fix style ([17c8fea](https://github.com/kailong321200875/vue-element-plus-admin/commit/17c8fea93811d9d9b708808484f5c907d761fcf1)) +- remove ContentDetailWrap style ([4ceaa9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/4ceaa9d7816369d0dcaf3e18e4cdbbd6165cef88)) + +### [1.2.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.2...v1.2.3) (2022-03-31) + +### Bug Fixes + +- fix refresh with query ([e94020f](https://github.com/kailong321200875/vue-element-plus-admin/commit/e94020ff541a061599486c0003258f1dbf13aba8)) + +### [1.2.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.1...v1.2.2) (2022-03-30) + +### Bug Fixes + +- fix avatar height bug ([cd4ab76](https://github.com/kailong321200875/vue-element-plus-admin/commit/cd4ab767018941777174d7837045f5259d1cc403)) +- fix parmas to params ([2c7211c](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c7211c89d7299ffc0a36bef8999b3c201dbaf4a)) + +### [1.2.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.2.0...v1.2.1) (2022-03-29) + +### Bug Fixes + +- fix invalid paging ([ad184ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/ad184ee9c0619da36f1ca3f26e67f18f88488523)) + +### Build System + +- update plugins ([0c7276f](https://github.com/kailong321200875/vue-element-plus-admin/commit/0c7276feadaedef83e6a4ad9d457e26d408698a8)) + +## [1.2.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.14...v1.2.0) (2022-03-27) + +### Features + +- add hooks demo ([c43f39e](https://github.com/kailong321200875/vue-element-plus-admin/commit/c43f39efef296266c64cc24690717d07fa0bcb85)) +- add inputPassword demo ([8f8b126](https://github.com/kailong321200875/vue-element-plus-admin/commit/8f8b1260e75df6998ebea617f62d4ab6be81d721)) + +### Docs + +- update LICENSE ([69d3dcc](https://github.com/kailong321200875/vue-element-plus-admin/commit/69d3dcc7edf69e9b4e3042ddb11faa85ec7d39e2)) + +### Styling + +- modify the function name to make it more semantic ([046ae51](https://github.com/kailong321200875/vue-element-plus-admin/commit/046ae512f02df2d3f08134949b9376a061c1eef3)) +- update Footer component presentation ([d4a9ba3](https://github.com/kailong321200875/vue-element-plus-admin/commit/d4a9ba3aa6758b8aac18b30e1a6b9501baff826c)) +- update Icon demo ([8597122](https://github.com/kailong321200875/vue-element-plus-admin/commit/85971227cd3055ea280cf493c7c42b250c1515da)) + +### Tests + +- test push first commit ([a67bb48](https://github.com/kailong321200875/vue-element-plus-admin/commit/a67bb48f269651a2dcd01b9e33d10f20c42d76ee)) + +### Build System + +- update plugins ([9c13d92](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c13d92b36a2a7c95b9edb7821367fc8f0ac6658)) +- update server port ([d2be8c1](https://github.com/kailong321200875/vue-element-plus-admin/commit/d2be8c1a307a3c5daf363bd7f1d21e574598de5c)) + +### [1.1.14](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.13...v1.1.14) (2022-03-22) + +### Bug Fixes + +- fix the bug that the form search function is invalid of the example-dialog page ([9ec30e7](https://github.com/kailong321200875/vue-element-plus-admin/commit/9ec30e719f89865497dbb1321be1df906f59f14e)) + +### [1.1.13](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.12...v1.1.13) (2022-03-17) + +### Build System + +- update plugins ([a2d0313](https://github.com/kailong321200875/vue-element-plus-admin/commit/a2d03137899f9b16fc1d4a09a23576cd74e7950e)) + +### [1.1.12](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.11...v1.1.12) (2022-03-15) + +### Build System + +- update plugins ([fee2252](https://github.com/kailong321200875/vue-element-plus-admin/commit/fee2252930b05b709d0c012e809568c4ed32bd89)) + +### [1.1.11](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.10...v1.1.11) (2022-03-15) + +### Bug Fixes + +- fix the problem of blank bar when toggle the TagsView component ([b1d9771](https://github.com/kailong321200875/vue-element-plus-admin/commit/b1d9771c750709fe45061d13299a85dbbd6ead25)) +- fix the problem that no reaction when copy setting config in http page ([61e0e33](https://github.com/kailong321200875/vue-element-plus-admin/commit/61e0e33c64d6a889fe6ed80d27a10cf8b201d21a)) + +### [1.1.10](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.9...v1.1.10) (2022-03-13) + +### Build System + +- update plugins ([0b525c8](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b525c875075a28288e92243b205b337f85ab550)) + +### [1.1.9](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.8...v1.1.9) (2022-03-07) + +### Build System + +- update plugins ([1456fd4](https://github.com/kailong321200875/vue-element-plus-admin/commit/1456fd49ec9abbfe1f25aeadfe5fed54fec07394)) + +### [1.1.8](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.7...v1.1.8) (2022-03-07) + +### Docs + +- update changelog ([bf09441](https://github.com/kailong321200875/vue-element-plus-admin/commit/bf09441852e59b0d07d4949a33de75958696817f)) + +### [1.1.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.6...v1.1.7) (2022-03-06) + +### Styling + +- add labelMessage attribute to Form component ([8c42790](https://github.com/kailong321200875/vue-element-plus-admin/commit/8c427907843ccb2dfd882d27c1e8a894c5616487)) + +### [1.1.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.5...v1.1.6) (2022-03-04) + +### Bug Fixes + +- fix the problem that the tree data of Table component cannot be displayed ([bf83d3e](https://github.com/kailong321200875/vue-element-plus-admin/commit/bf83d3efbad9097f245c32cc07d1178580cec4e3)) + +### [1.1.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.4...v1.1.5) (2022-03-02) + +### Bug Fixes + +- fix the problem of tagsview error when loginout ([835d76a](https://github.com/kailong321200875/vue-element-plus-admin/commit/835d76ae87b950106f957976ebc8f6f2e8842ddf)) + +### Build System + +- update plugins ([de34bb1](https://github.com/kailong321200875/vue-element-plus-admin/commit/de34bb193d6c844dbc1cec38db5f61b3f95e19f2)) + +### Styling + +- fix tabMenu z-index bug ([8b3be02](https://github.com/kailong321200875/vue-element-plus-admin/commit/8b3be02368a1bddb7dc78f18adbea7f4ebfe75d6)) +- fix tags-view style bug ([ebff817](https://github.com/kailong321200875/vue-element-plus-admin/commit/ebff81777b9c0b839256b83e321ecbdbff25fc73)) + +### [1.1.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.3...v1.1.4) (2022-03-01) + +### CI + +- update workflow ([0490d18](https://github.com/kailong321200875/vue-element-plus-admin/commit/0490d18145cb0d9c4b066ab01a2c10cb527e38ba)) +- update workflow ([51f7bca](https://github.com/kailong321200875/vue-element-plus-admin/commit/51f7bca6034902b251d081ee383b0d796782d434)) + +### [1.1.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.2...v1.1.3) (2022-03-01) + +### CI + +- update workflow ([91cc5c5](https://github.com/kailong321200875/vue-element-plus-admin/commit/91cc5c595cadc5695d8f54bdc4922d8f04439f24)) + +### [1.1.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.1...v1.1.2) (2022-03-01) + +### Workflows + +- update workflow ([d9708aa](https://github.com/kailong321200875/vue-element-plus-admin/commit/d9708aae5bc0cb795bb0fbf8d17df753cc88ba1d)) + +### [1.1.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.1.0...v1.1.1) (2022-03-01) + +### Workflows + +- update workflow ([085328a](https://github.com/kailong321200875/vue-element-plus-admin/commit/085328aba8c4f356bf7915a6bbdc1ec4f46ceeda)) + +## [1.1.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.0.3...v1.1.0) (2022-03-01) + +### Features + +- 🎸 layout 三种布局重构完成 ([429e428](https://github.com/kailong321200875/vue-element-plus-admin/commit/429e42809cef33a33662e41ad50297217d128b8c)) +- 🎸 layout 布局重构 �[bd24b92](https://github.com/kailong321200875/vue-element-plus-admin/commit/bd24b92acb279343dbaf83b74f1ed2a3f57f1003)) +- 🎸 Table 组件重构完成并给出相应示 �[35879f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/35879f8ecc0ffa76122a336e2eaa93ecfb408c1d)) +- 🎸 v0.0.4 发布 ([a58dc1b](https://github.com/kailong321200875/vue-element-plus-admin/commit/a58dc1b1c2774974782ef6d116b8805975b82b1c)) +- 🎸 初始化项 �[26d4c7c](https://github.com/kailong321200875/vue-element-plus-admin/commit/26d4c7c56894cf2031b3a7cce08d53c37f4a49e3)) +- 🎸 初版完成 ([5bfe4d2](https://github.com/kailong321200875/vue-element-plus-admin/commit/5bfe4d236fd9c2841da100f34c980b4572b67b20)) +- 🎸 新增 Detail 详情组件并给出相应示 �[e77a931](https://github.com/kailong321200875/vue-element-plus-admin/commit/e77a931ef2d2967a9717e27b187d68512c01284f)) +- 🎸 新增二维码组 �[85555ee](https://github.com/kailong321200875/vue-element-plus-admin/commit/85555eef7dc7d72cb701bdd81044ba8fb8e72acc)) +- 🎸 新增全局配置 ([f8405a6](https://github.com/kailong321200875/vue-element-plus-admin/commit/f8405a63c9b1288fbe95bae235b65a08e8fae8d2)) +- 🎸 新增固定 � 级菜单配 �[4c4903e](https://github.com/kailong321200875/vue-element-plus-admin/commit/4c4903e806c8818e320108cc3e5279d728061c29)) +- 🎸 新增权限管理及相关示例文 �[32b6583](https://github.com/kailong321200875/vue-element-plus-admin/commit/32b6583099646b2ee622ac7b35388468769b91b8)) +- 🎸 显示更多组建 � 发中 ([fa9f24d](https://github.com/kailong321200875/vue-element-plus-admin/commit/fa9f24d5da8d2e40d7c3661eabacb8f0474a7bf2)) +- 🎸 权限管理 � 发中 ([38f5211](https://github.com/kailong321200875/vue-element-plus-admin/commit/38f521174ba9eba750fee4516141d7a267f1c4ce)) +- 🎸 权限管理 � 发中 ([6d7ea66](https://github.com/kailong321200875/vue-element-plus-admin/commit/6d7ea6694d8299332018a6689bcd82502a9a552c)) +- 🎸 综合实例重构 �[5142e6e](https://github.com/kailong321200875/vue-element-plus-admin/commit/5142e6e323cb20c89a97398bf41d32c93ce42cad)) +- 🎸 重构 layout ([7ede021](https://github.com/kailong321200875/vue-element-plus-admin/commit/7ede02141e258ab4c88e9b4daad966513d4dbe68)) +- 🎸 重构 layout-classic 布局 ([29d9c98](https://github.com/kailong321200875/vue-element-plus-admin/commit/29d9c988605b822195900268da6bc3f3b0b9c770)) +- 🎸 重构 sider 组件 �[51313d7](https://github.com/kailong321200875/vue-element-plus-admin/commit/51313d7116c7ab2ded7e3a65514ea9ac413edecd)) +- Add analysis api ([83327ea](https://github.com/kailong321200875/vue-element-plus-admin/commit/83327ea763ebb233bb540513276ffa288fbcb4a1)) +- Add analysis demo ([cd06934](https://github.com/kailong321200875/vue-element-plus-admin/commit/cd069340fc5157535fdc82e792c6b6dce7d7a97e)) +- Add count-to demo ([d3fbd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d3fbd3a06c3b802fc863b4dc8013122c14bd16f2)) +- Add Descriptions component and add Descriptions demo ([7ad46f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/7ad46f828d626a87699cd4d3a959a5634577d580)) +- Add Dialog component and add dailog demo ([a18ad8f](https://github.com/kailong321200875/vue-element-plus-admin/commit/a18ad8f4a89b78c73e57d8d2543494243f656d05)) +- add doucment link ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- Add dynamic route ([9d926b2](https://github.com/kailong321200875/vue-element-plus-admin/commit/9d926b2760b75e1d8e71a68dc7ff6c5026223a43)) +- Add Editor component and add editor demo ([3fb3e8d](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fb3e8da39d816bcf4aedb65d40c7052bdb6d8bf)) +- Add Error component ([7411dbc](https://github.com/kailong321200875/vue-element-plus-admin/commit/7411dbc9fd8f122187c86a11523b49c88cc71a8c)) +- Add example-dialog demo ([262f421](https://github.com/kailong321200875/vue-element-plus-admin/commit/262f4211cf53aef30a32f4b88e88fb1b9246ffcb)) +- Add example-page demo ([1492f91](https://github.com/kailong321200875/vue-element-plus-admin/commit/1492f9119aa2960cc05956218e6d151c8b316875)) +- Add form demo ([472f574](https://github.com/kailong321200875/vue-element-plus-admin/commit/472f574f42f8f31c4e6047043ac755ba5fb35b7b)) +- Add form demo ([e6f9580](https://github.com/kailong321200875/vue-element-plus-admin/commit/e6f95803316bb5df2d1060285c1d591a79340721)) +- Add form demo ([543156f](https://github.com/kailong321200875/vue-element-plus-admin/commit/543156f328350bd12e71a41c872e547e41cda7fe)) +- Add form demo ([7795d2a](https://github.com/kailong321200875/vue-element-plus-admin/commit/7795d2a4fe3dbc9849ddc7c1d3e2d9215dc66f56)) +- Add guide demo ([0832194](https://github.com/kailong321200875/vue-element-plus-admin/commit/0832194e6131051416edff7c2eac6b0a016ffd80)) +- Add highlight demo ([eb206b0](https://github.com/kailong321200875/vue-element-plus-admin/commit/eb206b0cc31ac7da3dfd8b3d4b874061c5c91d53)) +- Add Icon demo ([e4b7a76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e4b7a769126d6f0fca424007c294ff229eefcb35)) +- Add ImageViewer component and add ImageViewer demo ([af9fc0a](https://github.com/kailong321200875/vue-element-plus-admin/commit/af9fc0a4aded3ec08746ddeaeabac4c3cfa9463d)) +- Add Infotip component ([e4b7a76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e4b7a769126d6f0fca424007c294ff229eefcb35)) +- Add infotip demo ([dbf3b0f](https://github.com/kailong321200875/vue-element-plus-admin/commit/dbf3b0f5a333ccef524bbac825035b0c6dc78ec9)) +- Add Qrcode component and add qrcode demo ([535a31b](https://github.com/kailong321200875/vue-element-plus-admin/commit/535a31b35eb6a76589f602fd96dcf91f46f349b0)) +- Add Search component and add search demo ([33eca8a](https://github.com/kailong321200875/vue-element-plus-admin/commit/33eca8a97d59f5cc453e1a60ee81b1519527d0f1)) +- Add Table component and add useTable hook ([17e8e7c](https://github.com/kailong321200875/vue-element-plus-admin/commit/17e8e7cda9a009818f11cfa0429ce0f9adc00be5)) +- Add useScrollTo hook ([7d7fd9e](https://github.com/kailong321200875/vue-element-plus-admin/commit/7d7fd9ed646d2b68cec0547ad8e65b0404bb95bb)) +- Add useWatermark hook and add useWatermark demo ([d3fbd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d3fbd3a06c3b802fc863b4dc8013122c14bd16f2)) +- Add workplace api ([cb558f8](https://github.com/kailong321200875/vue-element-plus-admin/commit/cb558f8af9dfef2ba2879f021db395ee79e8c8d4)) +- **Animate:** Add animate.css ([1436543](https://github.com/kailong321200875/vue-element-plus-admin/commit/1436543a5c599f651ed7805165ea83b9ebcddef5)) +- **Breadcrumbe:** Add Breadcrumb component ([4612e55](https://github.com/kailong321200875/vue-element-plus-admin/commit/4612e5544bcd626d686972e5cb874d0aa4af08b3)) +- **component:** Add CountTo component and Echart component ([e20fa76](https://github.com/kailong321200875/vue-element-plus-admin/commit/e20fa76cad0894a69fd04c81c2108faabf392684)) +- **component:** Add Footer component ([dad7330](https://github.com/kailong321200875/vue-element-plus-admin/commit/dad733063413c79eca61c6cb5ff671b35933a85f)) +- **component:** Add Footer component ([f81e996](https://github.com/kailong321200875/vue-element-plus-admin/commit/f81e996a426538aeaa2aa37a540395dcf360a09c)) +- **Component:** Add Highlight component ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- **component:** Add namespace of class ([d847ccb](https://github.com/kailong321200875/vue-element-plus-admin/commit/d847ccb098edc72fe55c1f8459bf149453a3b73d)) +- **Component:** Setting component add copy button ([e496096](https://github.com/kailong321200875/vue-element-plus-admin/commit/e496096539e6a56b0761a625c9d59210facc5432)) +- **ContextMenu:** Add ContextMenu component ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- Detail 组件重构完成 ([7f5ef99](https://github.com/kailong321200875/vue-element-plus-admin/commit/7f5ef99ccc32b03f7be21f70c333bb8e679c7d93)) +- Highlight 组件重构 ([34221f3](https://github.com/kailong321200875/vue-element-plus-admin/commit/34221f387f5e15a08cdc21edd76ce8d8c5c20fbc)) +- **hooks:** Add useIntro hook ([0832194](https://github.com/kailong321200875/vue-element-plus-admin/commit/0832194e6131051416edff7c2eac6b0a016ffd80)) +- **hooks:** Add useTimeAgo hook ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- **I18n:** Add Ii8n ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **Layout:** Add classic layout ([839b601](https://github.com/kailong321200875/vue-element-plus-admin/commit/839b6015b8e31bf70e6f0bf0608fa729b028729b)) +- **Layout:** Add cutMenu layout ([ff4dd3a](https://github.com/kailong321200875/vue-element-plus-admin/commit/ff4dd3afbf5c0c7a439c71b0c494b81e0f2c70d4)) +- **Layout:** Add topLeft layout ([71b1c5e](https://github.com/kailong321200875/vue-element-plus-admin/commit/71b1c5e10cade8d1c018d0c5f63c98ba9357bab8)) +- **LocaleDropdown:** Add LocaleDropdown Component ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **Logo:** Add Logo component ([958edef](https://github.com/kailong321200875/vue-element-plus-admin/commit/958edefe7bc2bf3ae77520a5d885a9d47e8a37b9)) +- **mock:** Add mock ([3fc7d4d](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fc7d4d39a72056fcf419fe19a9d41d90f945bad)) +- **router:** Add dynamic routing ([b218ccc](https://github.com/kailong321200875/vue-element-plus-admin/commit/b218ccc9cce2ce1363c4a21d22b4d69c43c7b2dc)) +- Search component add expand attribute and expandField attribute ([9b4b317](https://github.com/kailong321200875/vue-element-plus-admin/commit/9b4b31781765d31dec50acc40e2eed91401502d4)) +- **store:** Add localeStore ([3810b8c](https://github.com/kailong321200875/vue-element-plus-admin/commit/3810b8c3b26f86c27aa7db479dfb7b0d283d970f)) +- **store:** Add tagsView store ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- Table 组件重构 ([07adefb](https://github.com/kailong321200875/vue-element-plus-admin/commit/07adefb89b7555280e6217e09cf81ba7aa5b93c2)) +- **TagsView:** Add TagsView component ([349ac9d](https://github.com/kailong321200875/vue-element-plus-admin/commit/349ac9d3989d77e5246cecf0006dd8d83c489990)) +- **useForm:** Add useForm ([357fc44](https://github.com/kailong321200875/vue-element-plus-admin/commit/357fc44e519c5829567c17f611fcaadee3f9f933)) +- **useNProgress:** Add useNProgress ([c5ab359](https://github.com/kailong321200875/vue-element-plus-admin/commit/c5ab3599c8ea001ff7831b72fefc9e274163fbbb)) +- **useTitle:** Add useTitle ([c5ab359](https://github.com/kailong321200875/vue-element-plus-admin/commit/c5ab3599c8ea001ff7831b72fefc9e274163fbbb)) +- **utils:** Add color utils ([71dfba2](https://github.com/kailong321200875/vue-element-plus-admin/commit/71dfba21c5bc0276689b5aecf0d75e53efdda09f)) +- **VForm:** Add VForm component ([448ac52](https://github.com/kailong321200875/vue-element-plus-admin/commit/448ac5293e48a03840df2bb0b399a8f02aae666e)) +- **VInputPassword:** Add VInputPassword Component ([a1bf7e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/a1bf7e9b552f75d3b87c64904ac9e7c99fc936a5)) +- **Workplace:** Add wrokplace demo ([c53fa56](https://github.com/kailong321200875/vue-element-plus-admin/commit/c53fa562e540447df082e35c7f26e56f2426e430)) +- 综合实例、权限管理重 �[a4bd206](https://github.com/kailong321200875/vue-element-plus-admin/commit/a4bd2068a5d40d146b5b45cb3727ced990147b68)) +- 部分组件重构完成 ([3d96229](https://github.com/kailong321200875/vue-element-plus-admin/commit/3d9622978dc234ef12dbce63e18caf3440563aa0)) + +### Bug Fixes + +- 🐛 删除 Editor 双向绑定,改 �props 传参 ([c395e27](https://github.com/kailong321200875/vue-element-plus-admin/commit/c395e27f67af9f60b151a5484ab5a3c90c4c1d1e)) +- fix Form component setProps not work bug ([48ffc52](https://github.com/kailong321200875/vue-element-plus-admin/commit/48ffc52ca8fa26d8e6a5fa4b8b3001701a1f0732)) +- fix useScrollTo not work bug ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- 修复 tagsView 无动画效 �[0e3eb4b](https://github.com/kailong321200875/vue-element-plus-admin/commit/0e3eb4ba8b1503e1d221dfda59a3a0001dbdcb56)) + +### Performance Improvements + +- update useForm hook ([8a958cd](https://github.com/kailong321200875/vue-element-plus-admin/commit/8a958cd71d9afbd32b243aac0814bfa3281477cd)) + +### Code Refactoring + +- 💡 综合实例查看详情重构 ([9c26edd](https://github.com/kailong321200875/vue-element-plus-admin/commit/9c26edd5d599b5fb5a832fb547e3d95b6bfa9a98)) + +### Build System + +- Add conventional-changelog-cli plugin ([384485f](https://github.com/kailong321200875/vue-element-plus-admin/commit/384485f6994c6ac33abee506508ab9d35fe658a9)) +- Add conventional-github-releaser plugin ([3cd5c71](https://github.com/kailong321200875/vue-element-plus-admin/commit/3cd5c71899dde3ac3910aef0180d8b39fad51f1b)) +- Add standard-version plugin ([110ce25](https://github.com/kailong321200875/vue-element-plus-admin/commit/110ce257841648e29b247a0338624a188694b6e9)) +- Add vite-plugin-html plugin ([d5b6e2a](https://github.com/kailong321200875/vue-element-plus-admin/commit/d5b6e2a7770eb59aa32839f69da5be37397e3538)) +- delete useless plugin ([c756761](https://github.com/kailong321200875/vue-element-plus-admin/commit/c756761dfc3200156acb228474d3539197ef413b)) +- **pinia:** Add pinia ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **types:** Add vue-types ([2c41826](https://github.com/kailong321200875/vue-element-plus-admin/commit/2c41826c572268b74a663a6966c548628ac7e280)) +- **unplugin-auto-import:** Delete unplugin-auto-import ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **unplugin-vue-components:** Delete unplugin-vue-components ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- update plugin ([8d08bc6](https://github.com/kailong321200875/vue-element-plus-admin/commit/8d08bc6fc92258674abdd12834eaa4530ec276dd)) +- update plugins ([3c58042](https://github.com/kailong321200875/vue-element-plus-admin/commit/3c580420a20121845f02c0dd3caca5a74f06a89d)) +- **vite-plugin-style-import:** Add vite-plugin-style-import ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- **vite-plugin-vue-setup-extend:** Delete vite-plugin-vue-setup-extend ([2040500](https://github.com/kailong321200875/vue-element-plus-admin/commit/2040500af14d277a79f01eba5eca2a440203cecf)) +- 修改 vite 配置 ([9991fb4](https://github.com/kailong321200875/vue-element-plus-admin/commit/9991fb4e5c46b9e4016beaade7232e28dc272797)) +- 设置多语 �([45e879e](https://github.com/kailong321200875/vue-element-plus-admin/commit/45e879edeef677b6aa1d2cfe4dd8dc5b76c83c59)) +- 配置代码格式 �[ffdb556](https://github.com/kailong321200875/vue-element-plus-admin/commit/ffdb556a096db247306eae8eecc1b85718314cdd)) +- 集成基础配置 ([ced99de](https://github.com/kailong321200875/vue-element-plus-admin/commit/ced99de9b113a01d9d0b190f6d2c6adc983a3102)) +- 集成基础配置 ([5dbcf23](https://github.com/kailong321200875/vue-element-plus-admin/commit/5dbcf2397ccdec80c695c113f49e8aa9bb6d012c)) + +### Styling + +- 💄 优化 layout 样式 ([37ec378](https://github.com/kailong321200875/vue-element-plus-admin/commit/37ec378f0b2bf83d73ddf0e472aada6aab248f09)) +- 💄 微调样式 ([612b486](https://github.com/kailong321200875/vue-element-plus-admin/commit/612b48673c3389779ccfdd161e2ca80b21d265b2)) +- Add elNamespace ([d847ccb](https://github.com/kailong321200875/vue-element-plus-admin/commit/d847ccb098edc72fe55c1f8459bf149453a3b73d)) +- **appStore:** code style ([641ed68](https://github.com/kailong321200875/vue-element-plus-admin/commit/641ed684fefeb52e2f91e8baab7b610fc74c8d88)) +- **Breadcrumb:** fix Breadcrumb style bug ([8755c86](https://github.com/kailong321200875/vue-element-plus-admin/commit/8755c862b837d90a25b27c01fabe64abf81fc4a2)) +- **breadcrumb:** update disabled text color ([1522e92](https://github.com/kailong321200875/vue-element-plus-admin/commit/1522e925bae37cb9df4de2252d81f717788f4537)) +- change function to arrow function ([4612e55](https://github.com/kailong321200875/vue-element-plus-admin/commit/4612e5544bcd626d686972e5cb874d0aa4af08b3)) +- delete console.log ([49a6bfe](https://github.com/kailong321200875/vue-element-plus-admin/commit/49a6bfe9d81a40e2f5f15b68d7289e1787e89b54)) +- **Icon:** delete default color ([95a2bd8](https://github.com/kailong321200875/vue-element-plus-admin/commit/95a2bd884dd9846a56cda7c4c3ee4a41ce631b7c)) +- level demo style beautification ([dbf3b0f](https://github.com/kailong321200875/vue-element-plus-admin/commit/dbf3b0f5a333ccef524bbac825035b0c6dc78ec9)) +- lint code style ([b292419](https://github.com/kailong321200875/vue-element-plus-admin/commit/b2924190b8996e8208f951e3fadbcb09baddb8df)) +- **Login:** update login styles ([eb68f1d](https://github.com/kailong321200875/vue-element-plus-admin/commit/eb68f1d919e13c07b7d200e9aec53804b2a6dc7b)) +- modify menu z-index attribute ([0d7a778](https://github.com/kailong321200875/vue-element-plus-admin/commit/0d7a7781ce0b5e39f01355d3acdb3f364cabf76d)) +- **TagView:** Vertical center tag ([41281c4](https://github.com/kailong321200875/vue-element-plus-admin/commit/41281c4d541a2744e5df5dff2764cc85465b6a4c)) + +### Types + +- add ImportMetaEnv ([38e0257](https://github.com/kailong321200875/vue-element-plus-admin/commit/38e0257487e4138a74ad1bb4ee4ba004abcfaa12)) +- Adding BfFrom Component types ([8e036f5](https://github.com/kailong321200875/vue-element-plus-admin/commit/8e036f54b56ce8521eb8ec4b7ca21aa9c24f43f2)) +- **BfForm:** Adding BfForm types ([bc9195b](https://github.com/kailong321200875/vue-element-plus-admin/commit/bc9195b21eeb79629a82a04d90e2ac5aa6592928)) +- **BfForm:** Adding BfForm types ([184b468](https://github.com/kailong321200875/vue-element-plus-admin/commit/184b468cd41dcd1cdae11477b9ee2d6e17de1481)) +- **BfForm:** Adding BfForm types ([58cb24d](https://github.com/kailong321200875/vue-element-plus-admin/commit/58cb24d9f8a50be80b5ea793387d582a77a59137)) +- delete useless types ([3fc79c0](https://github.com/kailong321200875/vue-element-plus-admin/commit/3fc79c0ae7acd0929f47e33f96c8d45a90d8f762)) +- **VForm:** Adding VForm types ([7528fe6](https://github.com/kailong321200875/vue-element-plus-admin/commit/7528fe6da60368213d28d9f1b6310d02d3d53282)) + +### Docs + +- ✏️ 修改 readme ([8edb2a3](https://github.com/kailong321200875/vue-element-plus-admin/commit/8edb2a3493dca975036859b5d2c52afaa91f5dbb)) +- ✏️ 更新 readme ([62eeb55](https://github.com/kailong321200875/vue-element-plus-admin/commit/62eeb55330dd4af2a46801c7a19f38a3ef312bbf)) +- Add README.md ([21dcf88](https://github.com/kailong321200875/vue-element-plus-admin/commit/21dcf88ba31957bbdb50c6207d010650daab70fc)) +- Error modifying readme name ([25d5c84](https://github.com/kailong321200875/vue-element-plus-admin/commit/25d5c84e92e68aa72362a14f55aacd946fa5b1b2)) +- update description ([be6ff98](https://github.com/kailong321200875/vue-element-plus-admin/commit/be6ff9899b25cc00519210950d27ee56ac5112e6)) +- update description ([c15aa87](https://github.com/kailong321200875/vue-element-plus-admin/commit/c15aa8755c9c937512c7380a6d03c4d877ef4d87)) +- update README ([27979dc](https://github.com/kailong321200875/vue-element-plus-admin/commit/27979dc6def7d9d8cea62a08d49a6c828be2258b)) +- update README.md ([53201ae](https://github.com/kailong321200875/vue-element-plus-admin/commit/53201ae97a425714871d99e8847a3672ba0d389f)) +- update README.md ([c11823a](https://github.com/kailong321200875/vue-element-plus-admin/commit/c11823abd8a033e14b4c20d17ac941195d39bcfe)) +- 修改 README ([b79a567](https://github.com/kailong321200875/vue-element-plus-admin/commit/b79a56753df55976e749c4494266df052d315416)) diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 000000000..106259ce3 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM node:18.0.0 + +WORKDIR /app + +RUN npm install -g pnpm@8.1.0 + +COPY package.json . + +RUN pnpm install + +COPY . . + +CMD [ "pnpm", "run", "dev" ] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..9861118ae --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-present Archer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..0fbe3ca80 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +获取代码 +git clone +安装依赖 +cd vue-element-plus-admin +pnpm config set registry https://registry.npmmirror.com/ +pnpm install + +运行 +pnpm run dev +打包 +pnpm run build:pro + +问题 +1.集成到本地项目 本地启动运行可以看到设计器入口 +设计器是在开发环境提供辅助开发服务的,不是在线的 +在线参考 https://gitee.com/newgateway/vtj/tree/master/lcdp + +npm install -g lerna@latest pnpm@latest --registry=https://registry.npmmirror.com + +2.关于下载依赖报错:error (ERR_INVALID_THIS) +pnpm升级到 8.3.1 : + npm install -g pnpm@8.3.1 \ No newline at end of file diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 000000000..2b153a67c --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,148 @@ +


+ +[![license](https://img.shields.io/github/license/kailong321200875/vue-element-plus-admin.svg)](LICENSE) [![repo-size](https://img.shields.io/github/repo-size/kailong321200875/vue-element-plus-admin.svg)](repo-size) [![last-commit](https://img.shields.io/github/last-commit/kailong321200875/vue-element-plus-admin.svg)](last-commit) [![stars](https://img.shields.io/github/stars/kailong321200875/vue-element-plus-admin.svg)](stars) [![forks](https://img.shields.io/github/forks/kailong321200875/vue-element-plus-admin.svg)](forks) [![release](https://img.shields.io/github/release/kailong321200875/vue-element-plus-admin.svg)](release) [![watchers](https://img.shields.io/github/watchers/kailong321200875/vue-element-plus-admin.svg)](watchers) + +

vue-element-plus-admin

+
+ +[English](./README.md) | **中文** + +## 介绍 + +vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台模版。使用了最新的`vue3`,`vite`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,可以用来作为项目的启动模版,也可用于学习参考。并且时刻关注着最新技术动向,尽可能的第一时间更新。 + +vue-element-plus-admin 的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。 + +如需要基础模版,请切换到 `mini` 分支,`mini` 只简单集成了一些如:布局、动态菜单等常用布局功能,更适合开发者进行二次开发。 + +## 特性 + +- **最新技术栈**:使用 Vue3/vite4 等前端前沿技术开发 +- **TypeScript**: 应用程序级 JavaScript 的语言 +- **主题**: 可配置的主题 +- **国际化**:内置完善的国际化方案 +- **自定义数据** 内置 Mock 数据方案 +- **权限** 内置完善的动态路由权限生成方案 +- **组件** 二次封装了多个常用的组件 +- **示例** 内置丰富的示例 + +## 预览 + +- [vue-element-plus-admin](https://element-plus-admin.cn/) - 完整版 github 站点 +- [vue-element-plus-admin](https://kailong110120130.gitee.io/vue-element-plus-admin) - 完整版 gitee 站点 + +帐号:**admin/admin** + +在线例子默认不适用菜单过滤,而是直接使用静态路由表 + +## 文档 + +[文档地址 Github](https://element-plus-admin-doc.cn/) + +[文档地址 Gitee](https://kailong110120130.gitee.io/vue-element-plus-admin-doc) + +## 前序准备 + +- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) - 项目开发环境 +- [Vite](https://vitejs.dev/) - 熟悉 vite 特性 +- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法 +- [TypeScript](https://www.typescriptlang.org/) - 熟悉 `TypeScript` 基本语法 +- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法 +- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用 +- [Element-Plus](https://element-plus.org/) - element-plus 基本使用 +- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法 + +## 安装和使用 + +- 获取代码 + +```bash +git clone https://github.com/kailong321200875/vue-element-plus-admin.git +``` + +- 安装依赖 + +```bash +cd vue-element-plus-admin + +pnpm install + +``` + +- 运行 + +```bash +pnpm run dev +``` + +- 打包 + +```bash +pnpm run build:pro +``` + +## 更新日志 + +[更新日志](./CHANGELOG.md) + +## 如何贡献 + + + + + +你可以[提一个 issue](https://github.com/kailong321200875/vue-element-plus-admin/issues/new) 或者提交一个 Pull Request。 + +**Pull Request:** + +1. Fork 代码 +2. 创建自己的分支: `git checkout -b feat/xxxx` +3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'` +4. 推送您的分支: `git push origin feat/xxxx` +5. 提交 `pull request` + +## Git 贡献提交规范 + +- `feat` 新功能 +- `fix` 修补 bug +- `docs` 文档 +- `style` 格式、样式(不影响代码运行的变动) +- `refactor` 重构(即不是新增功能,也不是修改 BUG 的代码) +- `perf` 优化相关,比如提升性能、体验 +- `test` 添加测试 +- `build` 编译相关的修改,对项目构建或者依赖的改动 +- `ci` 持续集成修改 +- `chore` 构建过程或辅助工具的变动 +- `revert` 回滚到上一个版本 +- `workflow` 工作流改进 +- `mod` 不确定分类的修改 +- `wip` 开发中 +- `types` 类型 + +## 浏览器支持 + +本地开发推荐使用 `Chrome 80+` 浏览器 + +支持现代浏览器, 不支持 IE + +| [ Edge](http://godban.github.io/browsers-support-badges/)
IE | [ Edge](http://godban.github.io/browsers-support-badges/)
Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | +| :-: | :-: | :-: | :-: | :-: | +| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | + +## Donate + +如果你觉得这个项目有帮助,欢迎赞助以示支持~ + +[Paypal Me](https://www.paypal.com/paypalme/ckl94) + + + +### 我的二维码 + +如有项目合作或项目外包,扫码加我好友,请备注来意。 + + + +## 许可证 + +[MIT](./LICENSE) diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 000000000..78d145ddb --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1,28 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'type-enum': [ + 2, + 'always', + [ + 'feat', // 新功能(feature) + 'fix', // 修补bug + 'docs', // 文档(documentation) + 'style', // 格式、样式(不影响代码运行的变动) + 'refactor', // 重构(即不是新增功能,也不是修改BUG的代码) + 'perf', // 优化相关,比如提升性能、体验 + 'test', // 添加测试 + 'ci', // 持续集成修改 + 'chore', // 构建过程或辅助工具的变动 + 'revert', // 回滚到上一个版本 + 'workflow', // 工作流改进 + 'mod', // 不确定分类的修改 + 'wip', // 开发中 + 'types', // 类型修改 + 'release' // 版本发布 + ] + ], + 'subject-full-stop': [0, 'never'], + 'subject-case': [0, 'never'] + } +} diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml new file mode 100644 index 000000000..b6fd3e10b --- /dev/null +++ b/docker-compose.dev.yaml @@ -0,0 +1,10 @@ +services: + vue-element-plus-admin: + build: + context: . + dockerfile: Dockerfile.dev + ports: + - "4000:4000" + volumes: + - /app/node_modules + - .:/app \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..6c8a81fbc --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,81 @@ +// 引入vue模版的eslint +import pluginVue from 'eslint-plugin-vue' +import eslint from '@eslint/js' +// ts-eslint解析器,使 eslint 可以解析 ts 语法 +import tseslint from 'typescript-eslint' +// vue文件解析器 +import vueParser from 'vue-eslint-parser' +import prettier from 'eslint-plugin-prettier' + +export default tseslint.config({ + // ignores: ['node_modules', 'prettier.config.cjs', 'dist*'], + files: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'], + // tseslint.config添加了extends扁平函数,直接用。否则是eslint9.0版本是没有extends的 + extends: [ + eslint.configs.recommended, + ...tseslint.configs.recommended, + ...pluginVue.configs['flat/essential'] + ], + plugins: { + prettier + }, + languageOptions: { + parser: vueParser, // 使用vue解析器,这个可以识别vue文件 + parserOptions: { + parser: tseslint.parser, // 在vue文件上使用ts解析器 + sourceType: 'module', + ecmaVersion: 2020, + ecmaFeatures: { + jsx: true + } + } + }, + rules: { + 'prettier/prettier': 'error', + 'no-useless-escape': 0, + 'no-undef': 0, + 'vue/no-setup-props-destructure': 0, + 'vue/script-setup-uses-vars': 1, + 'vue/no-reserved-component-names': 0, + '@typescript-eslint/ban-ts-ignore': 0, + '@typescript-eslint/explicit-function-return-type': 0, + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-var-requires': 0, + '@typescript-eslint/no-empty-function': 0, + 'vue/custom-event-name-casing': 0, + 'no-use-before-define': 0, + '@typescript-eslint/no-use-before-define': 0, + '@typescript-eslint/ban-ts-comment': 0, + '@typescript-eslint/ban-types': 0, + '@typescript-eslint/no-non-null-assertion': 0, + '@typescript-eslint/explicit-module-boundary-types': 0, + '@typescript-eslint/no-unused-vars': 0, + 'no-unused-vars': 0, + 'space-before-function-paren': 0, + + 'vue/attributes-order': 0, + 'vue/one-component-per-file': 0, + 'vue/html-closing-bracket-newline': 0, + 'vue/max-attributes-per-line': 0, + 'vue/multiline-html-element-content-newline': 0, + 'vue/singleline-html-element-content-newline': 0, + 'vue/attribute-hyphenation': 0, + 'vue/require-default-prop': 0, + 'vue/require-explicit-emits': 0, + 'vue/html-self-closing': [ + 1, + { + html: { + void: 'always', + normal: 'never', + component: 'always' + }, + svg: 'always', + math: 'always' + } + ], + 'vue/multi-word-component-names': 0, + 'vue/no-v-html': 0, + 'vue/require-toggle-inside-transition': 0 + } +}) diff --git a/index.html b/index.html new file mode 100644 index 000000000..507d616e3 --- /dev/null +++ b/index.html @@ -0,0 +1,142 @@ + + + + + + + <%= title %> + + +
+ +
+
+
+ +
<%= title %>
+
+
+
+
+
+
+
+
+ + + diff --git a/mock/_createProductionServer.ts b/mock/_createProductionServer.ts new file mode 100644 index 000000000..598ac6490 --- /dev/null +++ b/mock/_createProductionServer.ts @@ -0,0 +1,18 @@ +import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' + +const modules = import.meta.glob('./**/*.mock.ts', { + import: 'default', + eager: true +}) + +const mockModules: any[] = [] +Object.keys(modules).forEach(async (key) => { + if (key.includes('_')) { + return + } + mockModules.push(...(modules[key] as any)) +}) + +export function setupProdMockServer() { + createProdMockServer(mockModules) +} diff --git a/mock/analysis/index.mock.ts b/mock/analysis/index.mock.ts new file mode 100644 index 000000000..195f3673b --- /dev/null +++ b/mock/analysis/index.mock.ts @@ -0,0 +1,87 @@ +import { SUCCESS_CODE } from '@/constants' +import { MockMethod } from 'vite-plugin-mock' + +const timeout = 1000 + +export default [ + // 分析页统计接口 + { + url: '/mock/analysis/total', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: { + users: 102400, + messages: 81212, + moneys: 9280, + shoppings: 13600 + } + } + } + }, + // 用户来源 + { + url: '/mock/analysis/userAccessSource', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { value: 1000, name: 'analysis.directAccess' }, + { value: 310, name: 'analysis.mailMarketing' }, + { value: 234, name: 'analysis.allianceAdvertising' }, + { value: 135, name: 'analysis.videoAdvertising' }, + { value: 1548, name: 'analysis.searchEngines' } + ] + } + } + }, + // 每周用户活跃量 + { + url: '/mock/analysis/weeklyUserActivity', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { value: 13253, name: 'analysis.monday' }, + { value: 34235, name: 'analysis.tuesday' }, + { value: 26321, name: 'analysis.wednesday' }, + { value: 12340, name: 'analysis.thursday' }, + { value: 24643, name: 'analysis.friday' }, + { value: 1322, name: 'analysis.saturday' }, + { value: 1324, name: 'analysis.sunday' } + ] + } + } + }, + // 每月销售额 + { + url: '/mock/analysis/monthlySales', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { estimate: 100, actual: 120, name: 'analysis.january' }, + { estimate: 120, actual: 82, name: 'analysis.february' }, + { estimate: 161, actual: 91, name: 'analysis.march' }, + { estimate: 134, actual: 154, name: 'analysis.april' }, + { estimate: 105, actual: 162, name: 'analysis.may' }, + { estimate: 160, actual: 140, name: 'analysis.june' }, + { estimate: 165, actual: 145, name: 'analysis.july' }, + { estimate: 114, actual: 250, name: 'analysis.august' }, + { estimate: 163, actual: 134, name: 'analysis.september' }, + { estimate: 185, actual: 56, name: 'analysis.october' }, + { estimate: 118, actual: 99, name: 'analysis.november' }, + { estimate: 123, actual: 123, name: 'analysis.december' } + ] + } + } + } +] as MockMethod[] diff --git a/mock/department/index.mock.ts b/mock/department/index.mock.ts new file mode 100644 index 000000000..443907ec0 --- /dev/null +++ b/mock/department/index.mock.ts @@ -0,0 +1,206 @@ +import { toAnyString } from '@/utils' +import Mock from 'mockjs' +import { SUCCESS_CODE } from '@/constants' + +const departmentList: any = [] + +const citys = ['厦门总公司', '北京分公司', '上海分公司', '福州分公司', '深圳分公司', '杭州分公司'] + +for (let i = 0; i < 5; i++) { + departmentList.push({ + // 部门名称 + departmentName: citys[i], + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)', + children: [ + { + // 部门名称 + departmentName: '研发部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + }, + { + // 部门名称 + departmentName: '产品部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + }, + { + // 部门名称 + departmentName: '运营部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + }, + { + // 部门名称 + departmentName: '市场部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + }, + { + // 部门名称 + departmentName: '销售部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + }, + { + // 部门名称 + departmentName: '客服部', + id: toAnyString(), + createTime: '@datetime', + // 状态 + status: Mock.Random.integer(0, 1), + // 备注 + remark: '@cword(10, 15)' + } + ] + }) +} + +export default [ + // 列表接口 + { + url: '/mock/department/list', + method: 'get', + response: () => { + return { + code: SUCCESS_CODE, + data: { + list: departmentList + } + } + } + }, + { + url: '/mock/department/table/list', + method: 'get', + response: () => { + return { + code: SUCCESS_CODE, + data: { + list: departmentList, + total: 5 + } + } + } + }, + { + url: '/mock/department/users', + method: 'get', + timeout: 1000, + response: ({ query }) => { + const { pageSize } = query + // 根据pageSize来创建数据 + const mockList: any = [] + for (let i = 0; i < pageSize; i++) { + mockList.push( + Mock.mock({ + // 用户名 + username: '@cname', + // 账号 + account: '@first', + // 邮箱 + email: '@EMAIL', + // 创建时间 + createTime: '@datetime', + // 用户id + id: toAnyString() + }) + ) + } + return { + code: SUCCESS_CODE, + data: { + total: 100, + list: mockList + } + } + } + }, + // 保存接口 + { + url: '/mock/department/user/save', + method: 'post', + timeout: 1000, + response: () => { + return { + code: SUCCESS_CODE, + data: 'success' + } + } + }, + // 删除接口 + { + url: '/mock/department/user/delete', + method: 'post', + response: ({ body }) => { + const ids = body.ids + if (!ids) { + return { + code: 500, + message: '请选择需要删除的数据' + } + } else { + return { + code: SUCCESS_CODE, + data: 'success' + } + } + } + }, + // 保存接口 + { + url: '/mock/department/save', + method: 'post', + timeout: 1000, + response: () => { + return { + code: SUCCESS_CODE, + data: 'success' + } + } + }, + // 删除接口 + { + url: '/mock/department/delete', + method: 'post', + response: ({ body }) => { + const ids = body.ids + if (!ids) { + return { + code: 500, + message: '请选择需要删除的数据' + } + } else { + return { + code: SUCCESS_CODE, + data: 'success' + } + } + } + } +] diff --git a/mock/dict/index.mock.ts b/mock/dict/index.mock.ts new file mode 100644 index 000000000..29042c63c --- /dev/null +++ b/mock/dict/index.mock.ts @@ -0,0 +1,60 @@ +import { SUCCESS_CODE } from '@/constants' + +const timeout = 1000 + +const dictObj: Recordable = { + importance: [ + { + value: 0, + label: 'tableDemo.commonly' + }, + { + value: 1, + label: 'tableDemo.good' + }, + { + value: 2, + label: 'tableDemo.important' + } + ] +} + +export default [ + // 字典接口 + { + url: '/mock/dict/list', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: dictObj + } + } + }, + // 获取某个字典 + { + url: '/mock/dict/one', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { + label: 'test1', + value: 0 + }, + { + label: 'test2', + value: 1 + }, + { + label: 'test3', + value: 2 + } + ] + } + } + } +] diff --git a/mock/menu/index.mock.ts b/mock/menu/index.mock.ts new file mode 100644 index 000000000..282369200 --- /dev/null +++ b/mock/menu/index.mock.ts @@ -0,0 +1,357 @@ +import Mock from 'mockjs' +import { SUCCESS_CODE } from '@/constants' + +const timeout = 1000 + +export default [ + // 列表接口 + { + url: '/mock/menu/list', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: { + list: [ + { + path: '/dashboard', + component: '#', + redirect: '/dashboard/analysis', + name: 'Dashboard', + status: Mock.Random.integer(0, 1), + id: 1, + type: 0, + parentId: undefined, + title: '首页', + meta: { + title: '首页', + icon: 'vi-ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: 'views/Dashboard/Analysis', + name: 'Analysis', + status: Mock.Random.integer(0, 1), + id: 2, + type: 1, + parentId: 1, + title: '分析页', + permissionList: [ + { + id: 1, + label: '新增', + value: 'add' + }, + { + id: 2, + label: '编辑', + value: 'edit' + } + ], + meta: { + title: '分析页', + noCache: true, + permission: ['add', 'edit'] + } + }, + { + path: 'workplace', + component: 'views/Dashboard/Workplace', + name: 'Workplace', + status: Mock.Random.integer(0, 1), + id: 3, + type: 1, + parentId: 1, + title: '工作台', + permissionList: [ + { + id: 1, + label: '新增', + value: 'add' + }, + { + id: 2, + label: '编辑', + value: 'edit' + }, + { + id: 3, + label: '删除', + value: 'delete' + } + ], + meta: { + title: '工作台', + noCache: true + } + } + ] + }, + { + path: '/external-link', + component: '#', + meta: { + title: '文档', + icon: 'vi-clarity:document-solid' + }, + name: 'ExternalLink', + status: Mock.Random.integer(0, 1), + id: 4, + type: 0, + parentId: undefined, + title: '文档', + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + status: Mock.Random.integer(0, 1), + id: 5, + type: 1, + parentId: 4, + title: '文档', + meta: { + title: '文档' + } + } + ] + }, + { + path: '/level', + component: '#', + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + status: Mock.Random.integer(0, 1), + id: 6, + type: 0, + parentId: undefined, + title: '菜单', + meta: { + title: '菜单', + icon: 'vi-carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: '##', + status: Mock.Random.integer(0, 1), + id: 7, + type: 0, + parentId: 6, + title: '菜单1', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1' + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: '##', + status: Mock.Random.integer(0, 1), + id: 8, + type: 0, + parentId: 7, + title: '菜单1-1', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1-1', + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: 'views/Level/Menu111', + status: Mock.Random.integer(0, 1), + id: 9, + type: 1, + parentId: 8, + title: '菜单1-1-1', + meta: { + title: '菜单1-1-1' + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: 'views/Level/Menu12', + status: Mock.Random.integer(0, 1), + id: 10, + type: 1, + parentId: 7, + title: '菜单1-2', + meta: { + title: '菜单1-2' + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: 'views/Level/Menu2', + status: Mock.Random.integer(0, 1), + id: 11, + type: 1, + parentId: 6, + title: '菜单2', + meta: { + title: '菜单2' + } + } + ] + }, + { + path: '/example', + component: '#', + redirect: '/example/example-dialog', + name: 'Example', + status: Mock.Random.integer(0, 1), + id: 12, + type: 0, + parentId: undefined, + title: '综合示例', + meta: { + title: '综合示例', + icon: 'vi-ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-dialog', + component: 'views/Example/Dialog/ExampleDialog', + name: 'ExampleDialog', + status: Mock.Random.integer(0, 1), + id: 13, + type: 1, + parentId: 12, + title: '综合示例-弹窗', + permissionList: [ + { + id: 1, + label: '新增', + value: 'add' + }, + { + id: 2, + label: '编辑', + value: 'edit' + }, + { + id: 3, + label: '删除', + value: 'delete' + }, + { + id: 4, + label: '查看', + value: 'view' + } + ], + meta: { + title: '综合示例-弹窗' + } + }, + { + path: 'example-page', + component: 'views/Example/Page/ExamplePage', + name: 'ExamplePage', + status: Mock.Random.integer(0, 1), + id: 14, + type: 1, + parentId: 12, + title: '综合示例-页面', + permissionList: [ + { + id: 1, + label: '新增', + value: 'add' + }, + { + id: 2, + label: '编辑', + value: 'edit' + }, + { + id: 3, + label: '删除', + value: 'delete' + }, + { + id: 4, + label: '查看', + value: 'view' + } + ], + meta: { + title: '综合示例-页面' + } + }, + { + path: 'example-add', + component: 'views/Example/Page/ExampleAdd', + name: 'ExampleAdd', + status: Mock.Random.integer(0, 1), + id: 15, + type: 1, + parentId: 12, + title: '综合示例-新增', + meta: { + title: '综合示例-新增', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-edit', + component: 'views/Example/Page/ExampleEdit', + name: 'ExampleEdit', + status: Mock.Random.integer(0, 1), + id: 16, + type: 1, + parentId: 12, + title: '综合示例-编辑', + meta: { + title: '综合示例-编辑', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-detail', + component: 'views/Example/Page/ExampleDetail', + name: 'ExampleDetail', + status: Mock.Random.integer(0, 1), + id: 17, + type: 1, + parentId: 12, + title: '综合示例-详情', + meta: { + title: '综合示例-详情', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + } + ] + } + ] + } + } + } + } +] diff --git a/mock/request/index.mock.ts b/mock/request/index.mock.ts new file mode 100644 index 000000000..bfaa26698 --- /dev/null +++ b/mock/request/index.mock.ts @@ -0,0 +1,72 @@ +import { SUCCESS_CODE } from '@/constants' + +const timeout = 600000 + +export default [ + { + url: '/mock/request/1', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: 'request-1' + } + } + }, + { + url: '/mock/request/2', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: 'request-2' + } + } + }, + { + url: '/mock/request/3', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: 'request-3' + } + } + }, + { + url: '/mock/request/4', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: 'request-4' + } + } + }, + { + url: '/mock/request/5', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: 'request-5' + } + } + }, + { + url: '/mock/request/expired', + method: 'get', + timeout: 0, + response: () => { + return { + code: 401, + message: 'token expired' + } + } + } +] diff --git a/mock/role/index.mock.ts b/mock/role/index.mock.ts new file mode 100644 index 000000000..a0ec69c62 --- /dev/null +++ b/mock/role/index.mock.ts @@ -0,0 +1,1227 @@ +import Mock from 'mockjs' +import { SUCCESS_CODE } from '@/constants' +import { toAnyString } from '@/utils' + +const timeout = 1000 + +const adminList = [ + { + path: '/dashboard', + component: '#', + redirect: '/dashboard/analysis', + name: 'Dashboard', + meta: { + title: 'router.dashboard', + icon: 'vi-ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: 'views/Dashboard/Analysis', + name: 'Analysis', + meta: { + title: 'router.analysis', + noCache: true, + affix: true + } + }, + { + path: 'workplace', + component: 'views/Dashboard/Workplace', + name: 'Workplace', + meta: { + title: 'router.workplace', + noCache: true, + affix: true + } + } + ] + }, + { + path: '/external-link', + component: '#', + meta: {}, + name: 'ExternalLink', + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + meta: { + title: 'router.document', + icon: 'vi-clarity:document-solid' + } + } + ] + }, + { + path: '/guide', + component: '#', + name: 'Guide', + meta: {}, + children: [ + { + path: 'index', + component: 'views/Guide/Guide', + name: 'GuideDemo', + meta: { + title: 'router.guide', + icon: 'vi-cib:telegram-plane' + } + } + ] + }, + { + path: '/components', + component: '#', + redirect: '/components/form/default-form', + name: 'ComponentsDemo', + meta: { + title: 'router.component', + icon: 'vi-bx:bxs-component', + alwaysShow: true + }, + children: [ + { + path: 'form', + component: '##', + name: 'Form', + meta: { + title: 'router.form', + alwaysShow: true + }, + children: [ + { + path: 'default-form', + component: 'views/Components/Form/DefaultForm', + name: 'DefaultForm', + meta: { + title: 'router.defaultForm' + } + }, + { + path: 'use-form', + component: 'views/Components/Form/UseFormDemo', + name: 'UseForm', + meta: { + title: 'UseForm' + } + } + ] + }, + { + path: 'table', + component: '##', + redirect: '/components/table/default-table', + name: 'TableDemo', + meta: { + title: 'router.table', + alwaysShow: true + }, + children: [ + { + path: 'default-table', + component: 'views/Components/Table/DefaultTable', + name: 'DefaultTable', + meta: { + title: 'router.defaultTable' + } + }, + { + path: 'use-table', + component: 'views/Components/Table/UseTableDemo', + name: 'UseTable', + meta: { + title: 'UseTable' + } + }, + { + path: 'tree-table', + component: 'views/Components/Table/TreeTable', + name: 'TreeTable', + meta: { + title: 'TreeTable' + } + }, + { + path: 'table-image-preview', + component: 'views/Components/Table/TableImagePreview', + name: 'TableImagePreview', + meta: { + title: 'router.PicturePreview' + } + }, + { + path: 'table-video-preview', + component: 'views/Components/Table/TableVideoPreview', + name: 'TableVideoPreview', + meta: { + title: 'router.tableVideoPreview' + } + }, + { + path: 'card-table', + component: 'views/Components/Table/CardTable', + name: 'CardTable', + meta: { + title: 'router.cardTable' + } + } + // { + // path: 'ref-table', + // component: 'views/Components/Table/RefTable', + // name: 'RefTable', + // meta: { + // title: 'RefTable' + // } + // } + ] + }, + { + path: 'editor-demo', + component: '##', + redirect: '/components/editor-demo/editor', + name: 'EditorDemo', + meta: { + title: 'router.editor', + alwaysShow: true + }, + children: [ + { + path: 'editor', + component: 'views/Components/Editor/Editor', + name: 'Editor', + meta: { + title: 'router.richText' + } + }, + { + path: 'json-editor', + component: 'views/Components/Editor/JsonEditor', + name: 'JsonEditor', + meta: { + title: 'router.jsonEditor' + } + }, + { + path: 'code-editor', + component: 'views/Components/Editor/CodeEditor', + name: 'CodeEditor', + meta: { + title: 'router.codeEditor' + } + } + ] + }, + { + path: 'search', + component: 'views/Components/Search', + name: 'Search', + meta: { + title: 'router.search' + } + }, + { + path: 'descriptions', + component: 'views/Components/Descriptions', + name: 'Descriptions', + meta: { + title: 'router.descriptions' + } + }, + { + path: 'image-viewer', + component: 'views/Components/ImageViewer', + name: 'ImageViewer', + meta: { + title: 'router.imageViewer' + } + }, + { + path: 'dialog', + component: 'views/Components/Dialog', + name: 'Dialog', + meta: { + title: 'router.dialog' + } + }, + { + path: 'icon', + component: 'views/Components/Icon', + name: 'Icon', + meta: { + title: 'router.icon' + } + }, + { + path: 'icon-picker', + component: 'views/Components/IconPicker', + name: 'IconPicker', + meta: { + title: 'router.iconPicker' + } + }, + { + path: 'echart', + component: 'views/Components/Echart', + name: 'Echart', + meta: { + title: 'router.echart' + } + }, + { + path: 'count-to', + component: 'views/Components/CountTo', + name: 'CountTo', + meta: { + title: 'router.countTo' + } + }, + { + path: 'qrcode', + component: 'views/Components/Qrcode', + name: 'Qrcode', + meta: { + title: 'router.qrcode' + } + }, + { + path: 'highlight', + component: 'views/Components/Highlight', + name: 'Highlight', + meta: { + title: 'router.highlight' + } + }, + { + path: 'infotip', + component: 'views/Components/Infotip', + name: 'Infotip', + meta: { + title: 'router.infotip' + } + }, + { + path: 'input-password', + component: 'views/Components/InputPassword', + name: 'InputPassword', + meta: { + title: 'router.inputPassword' + } + }, + { + path: 'waterfall', + component: 'views/Components/Waterfall', + name: 'Waterfall', + meta: { + title: 'router.waterfall' + } + }, + { + path: 'image-cropping', + component: 'views/Components/ImageCropping', + name: 'ImageCropping', + meta: { + title: 'router.imageCropping' + } + }, + { + path: 'video-player', + component: 'views/Components/VideoPlayer', + name: 'VideoPlayer', + meta: { + title: 'router.videoPlayer' + } + }, + { + path: 'avatars', + component: 'views/Components/Avatars', + name: 'Avatars', + meta: { + title: 'router.avatars' + } + }, + { + path: 'i-agree', + component: 'views/Components/IAgree', + name: 'IAgree', + meta: { + title: 'router.iAgree' + } + } + ] + }, + { + path: '/function', + component: '#', + redirect: '/function/multipleTabs', + name: 'Function', + meta: { + title: 'router.function', + icon: 'vi-ri:function-fill', + alwaysShow: true + }, + children: [ + { + path: 'multipleTabs', + component: 'views/Function/MultipleTabs', + name: 'MultipleTabs', + meta: { + title: 'router.multipleTabs' + } + }, + { + path: 'multiple-tabs-demo/:id', + component: 'views/Function/MultipleTabsDemo', + name: 'MultipleTabsDemo', + meta: { + hidden: true, + title: 'router.details', + canTo: true + } + }, + { + path: 'request', + component: 'views/Function/Request', + name: 'Request', + meta: { + title: 'router.request' + } + }, + { + path: 'test', + component: 'views/Function/Test', + name: 'Test', + meta: { + title: 'router.permission', + permission: ['add', 'edit', 'delete'] + } + } + ] + }, + { + path: '/hooks', + component: '#', + redirect: '/hooks/useWatermark', + name: 'Hooks', + meta: { + title: 'hooks', + icon: 'vi-ic:outline-webhook', + alwaysShow: true + }, + children: [ + { + path: 'useWatermark', + component: 'views/hooks/useWatermark', + name: 'UseWatermark', + meta: { + title: 'useWatermark' + } + }, + { + path: 'useTagsView', + component: 'views/hooks/useTagsView', + name: 'UseTagsView', + meta: { + title: 'useTagsView' + } + }, + { + path: 'useValidator', + component: 'views/hooks/useValidator', + name: 'UseValidator', + meta: { + title: 'useValidator' + } + }, + { + path: 'useCrudSchemas', + component: 'views/hooks/useCrudSchemas', + name: 'UseCrudSchemas', + meta: { + title: 'useCrudSchemas' + } + }, + { + path: 'useClipboard', + component: 'views/hooks/useClipboard', + name: 'UseClipboard', + meta: { + title: 'useClipboard' + } + }, + { + path: 'useNetwork', + component: 'views/hooks/useNetwork', + name: 'UseNetwork', + meta: { + title: 'useNetwork' + } + } + ] + }, + { + path: '/level', + component: '#', + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + meta: { + title: 'router.level', + icon: 'vi-carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: '##', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: 'router.menu1' + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: '##', + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: 'router.menu11', + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: 'views/Level/Menu111', + meta: { + title: 'router.menu111' + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: 'views/Level/Menu12', + meta: { + title: 'router.menu12' + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: 'views/Level/Menu2', + meta: { + title: 'router.menu2' + } + } + ] + }, + { + path: '/example', + component: '#', + redirect: '/example/example-dialog', + name: 'Example', + meta: { + title: 'router.example', + icon: 'vi-ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-dialog', + component: 'views/Example/Dialog/ExampleDialog', + name: 'ExampleDialog', + meta: { + title: 'router.exampleDialog' + } + }, + { + path: 'example-page', + component: 'views/Example/Page/ExamplePage', + name: 'ExamplePage', + meta: { + title: 'router.examplePage' + } + }, + { + path: 'example-add', + component: 'views/Example/Page/ExampleAdd', + name: 'ExampleAdd', + meta: { + title: 'router.exampleAdd', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-edit', + component: 'views/Example/Page/ExampleEdit', + name: 'ExampleEdit', + meta: { + title: 'router.exampleEdit', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-detail', + component: 'views/Example/Page/ExampleDetail', + name: 'ExampleDetail', + meta: { + title: 'router.exampleDetail', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page' + } + } + ] + }, + { + path: '/error', + component: '#', + redirect: '/error/404', + name: 'Error', + meta: { + title: 'router.errorPage', + icon: 'vi-ci:error', + alwaysShow: true + }, + children: [ + { + path: '404-demo', + component: 'views/Error/404', + name: '404Demo', + meta: { + title: '404' + } + }, + { + path: '403-demo', + component: 'views/Error/403', + name: '403Demo', + meta: { + title: '403' + } + }, + { + path: '500-demo', + component: 'views/Error/500', + name: '500Demo', + meta: { + title: '500' + } + } + ] + }, + { + path: '/authorization', + component: '#', + redirect: '/authorization/user', + name: 'Authorization', + meta: { + title: 'router.authorization', + icon: 'vi-eos-icons:role-binding', + alwaysShow: true + }, + children: [ + { + path: 'department', + component: 'views/Authorization/Department/Department', + name: 'Department', + meta: { + title: 'router.department' + } + }, + { + path: 'user', + component: 'views/Authorization/User/User', + name: 'User', + meta: { + title: 'router.user' + } + }, + { + path: 'menu', + component: 'views/Authorization/Menu/Menu', + name: 'Menu', + meta: { + title: 'router.menuManagement' + } + }, + { + path: 'role', + component: 'views/Authorization/Role/Role', + name: 'Role', + meta: { + title: 'router.role' + } + } + ] + } +] + +const testList: string[] = [ + '/dashboard', + '/dashboard/analysis', + '/dashboard/workplace', + 'external-link', + 'https://element-plus-admin-doc.cn/', + '/guide', + '/guide/index', + '/components', + '/components/form', + '/components/form/default-form', + '/components/form/use-form', + '/components/form/ref-form', + '/components/table', + '/components/table/default-table', + '/components/table/use-table', + '/components/table/tree-table', + '/components/table/table-image-preview', + '/components/table/table-video-preview', + '/components/table/ref-table', + '/components/table/card-table', + '/components/editor-demo', + '/components/editor-demo/editor', + '/components/editor-demo/json-editor', + '/components/editor-demo/code-editor', + '/components/search', + '/components/descriptions', + '/components/image-viewer', + '/components/dialog', + '/components/icon', + '/components/iconPicker', + '/components/echart', + '/components/count-to', + '/components/qrcode', + '/components/highlight', + '/components/infotip', + '/components/input-password', + '/components/waterfall', + '/components/image-cropping', + '/components/video-player', + '/components/avatars', + '/components/i-agree', + 'function', + '/function/multiple-tabs', + '/function/multiple-tabs-demo/:id', + '/function/request', + '/function/test', + '/hooks', + '/hooks/useWatermark', + '/hooks/useTagsView', + '/hooks/useValidator', + '/hooks/useCrudSchemas', + '/hooks/useClipboard', + '/hooks/useNetwork', + '/level', + '/level/menu1', + '/level/menu1/menu1-1', + '/level/menu1/menu1-1/menu1-1-1', + '/level/menu1/menu1-2', + '/level/menu2', + '/example', + '/example/example-dialog', + '/example/example-page', + '/example/example-add', + '/example/example-edit', + '/example/example-detail', + '/authorization', + '/authorization/department', + '/authorization/user', + '/authorization/role', + '/authorization/menu', + '/error', + '/error/404-demo', + '/error/403-demo', + '/error/500-demo' +] + +const List: any[] = [] + +const roleNames = ['超级管理员', '管理员', '普通用户', '游客'] +const menus = [ + [ + { + path: '/dashboard', + component: '#', + redirect: '/dashboard/analysis', + name: 'Dashboard', + status: Mock.Random.integer(0, 1), + id: 1, + meta: { + title: '首页', + icon: 'vi-ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: 'views/Dashboard/Analysis', + name: 'Analysis', + status: Mock.Random.integer(0, 1), + id: 2, + meta: { + title: '分析页', + noCache: true + } + }, + { + path: 'workplace', + component: 'views/Dashboard/Workplace', + name: 'Workplace', + status: Mock.Random.integer(0, 1), + id: 3, + meta: { + title: '工作台', + noCache: true + } + } + ] + }, + { + path: '/external-link', + component: '#', + meta: { + title: '文档', + icon: 'vi-clarity:document-solid' + }, + name: 'ExternalLink', + status: Mock.Random.integer(0, 1), + id: 4, + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + status: Mock.Random.integer(0, 1), + id: 5, + meta: { + title: '文档' + } + } + ] + }, + { + path: '/level', + component: '#', + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + status: Mock.Random.integer(0, 1), + id: 6, + meta: { + title: '菜单', + icon: 'vi-carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: '##', + status: Mock.Random.integer(0, 1), + id: 7, + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1' + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: '##', + status: Mock.Random.integer(0, 1), + id: 8, + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1-1', + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: 'views/Level/Menu111', + status: Mock.Random.integer(0, 1), + id: 9, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单1-1-1', + permission: ['edit', 'add', 'delete'] + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: 'views/Level/Menu12', + status: Mock.Random.integer(0, 1), + id: 10, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单1-2', + permission: ['edit', 'add', 'delete'] + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: 'views/Level/Menu2', + status: Mock.Random.integer(0, 1), + id: 11, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单2', + permission: ['edit', 'add', 'delete'] + } + } + ] + }, + { + path: '/example', + component: '#', + redirect: '/example/example-dialog', + name: 'Example', + status: Mock.Random.integer(0, 1), + id: 12, + meta: { + title: '综合示例', + icon: 'vi-ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-dialog', + component: 'views/Example/Dialog/ExampleDialog', + name: 'ExampleDialog', + status: Mock.Random.integer(0, 1), + id: 13, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-弹窗', + permission: ['edit', 'add', 'delete'] + } + }, + { + path: 'example-page', + component: 'views/Example/Page/ExamplePage', + name: 'ExamplePage', + status: Mock.Random.integer(0, 1), + id: 14, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-页面', + permission: ['edit', 'add', 'delete'] + } + }, + { + path: 'example-add', + component: 'views/Example/Page/ExampleAdd', + name: 'ExampleAdd', + status: Mock.Random.integer(0, 1), + id: 15, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-新增', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page', + permission: ['edit', 'add', 'delete'] + } + }, + { + path: 'example-edit', + component: 'views/Example/Page/ExampleEdit', + name: 'ExampleEdit', + status: Mock.Random.integer(0, 1), + id: 16, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-编辑', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page', + permission: ['edit', 'add', 'delete'] + } + }, + { + path: 'example-detail', + component: 'views/Example/Page/ExampleDetail', + name: 'ExampleDetail', + status: Mock.Random.integer(0, 1), + id: 17, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-详情', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page', + permission: ['edit', 'add', 'delete'] + } + } + ] + } + ], + [ + { + path: '/dashboard', + component: '#', + redirect: '/dashboard/analysis', + name: 'Dashboard', + status: Mock.Random.integer(0, 1), + id: 1, + meta: { + title: '首页', + icon: 'vi-ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: 'views/Dashboard/Analysis', + name: 'Analysis', + status: Mock.Random.integer(0, 1), + id: 2, + meta: { + title: '分析页', + noCache: true + } + }, + { + path: 'workplace', + component: 'views/Dashboard/Workplace', + name: 'Workplace', + status: Mock.Random.integer(0, 1), + id: 3, + meta: { + title: '工作台', + noCache: true + } + } + ] + } + ], + [ + { + path: '/external-link', + component: '#', + meta: { + title: '文档', + icon: 'vi-clarity:document-solid' + }, + name: 'ExternalLink', + status: Mock.Random.integer(0, 1), + id: 4, + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + status: Mock.Random.integer(0, 1), + id: 5, + meta: { + title: '文档' + } + } + ] + }, + { + path: '/level', + component: '#', + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + status: Mock.Random.integer(0, 1), + id: 6, + meta: { + title: '菜单', + icon: 'vi-carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: '##', + status: Mock.Random.integer(0, 1), + id: 7, + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1' + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: '##', + status: Mock.Random.integer(0, 1), + id: 8, + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: '菜单1-1', + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: 'views/Level/Menu111', + status: Mock.Random.integer(0, 1), + id: 9, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单1-1-1', + permission: ['edit', 'add', 'delete'] + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: 'views/Level/Menu12', + status: Mock.Random.integer(0, 1), + id: 10, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单1-2', + permission: ['edit', 'add', 'delete'] + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: 'views/Level/Menu2', + status: Mock.Random.integer(0, 1), + id: 11, + permission: ['edit', 'add', 'delete'], + meta: { + title: '菜单2', + permission: ['edit', 'add', 'delete'] + } + } + ] + } + ], + [ + { + path: '/example', + component: '#', + redirect: '/example/example-dialog', + name: 'Example', + status: Mock.Random.integer(0, 1), + id: 12, + meta: { + title: '综合示例', + icon: 'vi-ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-detail', + component: 'views/Example/Page/ExampleDetail', + name: 'ExampleDetail', + status: Mock.Random.integer(0, 1), + id: 17, + permission: ['edit', 'add', 'delete'], + meta: { + title: '综合示例-详情', + noTagsView: true, + noCache: true, + hidden: true, + showMainRoute: true, + activeMenu: '/example/example-page', + permission: ['edit', 'add', 'delete'] + } + } + ] + } + ] +] + +for (let i = 0; i < 4; i++) { + List.push( + Mock.mock({ + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + roleName: roleNames[i], + role: '@first', + status: Mock.Random.integer(0, 1), + createTime: '@datetime', + remark: '@cword(10, 15)', + menu: menus[i] + }) + ) +} + +export default [ + // 列表接口 + { + url: '/mock/role/list', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: adminList + } + } + }, + { + url: '/mock/role/table', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: { + list: List, + total: 4 + } + } + } + }, + // 列表接口 + { + url: '/mock/role/list2', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: testList + } + } + }, + { + url: '/mock/role/table', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: { + list: List, + total: 4 + } + } + } + } +] diff --git a/mock/table/index.mock.ts b/mock/table/index.mock.ts new file mode 100644 index 000000000..a83ed140e --- /dev/null +++ b/mock/table/index.mock.ts @@ -0,0 +1,319 @@ +import Mock from 'mockjs' +import { SUCCESS_CODE } from '@/constants' +import { toAnyString } from '@/utils' + +const timeout = 1000 +const count = 100 + +const baseContent = + '

I am testing data, I am testing data.

' + +interface ListProps { + id: string + author: string + title: string + content: string + importance: number + display_time: any + pageviews: number + image_uri: string + video_uri?: string +} + +interface TreeListProps { + id: string + author: string + title: string + content: string + importance: number + display_time: any + image_uri: string + pageviews: number + video_uri?: string + children?: TreeListProps[] +} + +let List: ListProps[] = [] + +for (let i = 0; i < count; i++) { + List.push( + Mock.mock({ + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(100, 500)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'), + video_uri: + '//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4' + }) + ) +} + +const treeList: TreeListProps[] = [] + +for (let i = 0; i < count; i++) { + treeList.push( + Mock.mock({ + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'), + children: [ + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'), + children: [ + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)') + }, + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)') + } + ] + }, + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)') + }, + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)') + }, + { + id: toAnyString(), + // timestamp: +Mock.Random.date('T'), + author: '@first', + title: '@title(5, 10)', + content: baseContent, + importance: '@integer(1, 3)', + display_time: '@datetime', + pageviews: '@integer(300, 5000)', + image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)') + } + ] + // image_uri + }) + ) +} + +const cardList = [ + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png', + name: 'Alipay', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + }, + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png', + name: 'Angular', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + }, + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png', + name: 'Bootstrap', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + }, + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png', + name: 'React', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + }, + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png', + name: 'Vue', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + }, + { + logo: 'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', + name: 'Webpack', + desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。' + } +] + +export default [ + // 树形列表接口 + { + url: '/mock/example/treeList', + method: 'get', + timeout, + response: ({ query }) => { + const { title, pageIndex, pageSize } = query + const mockList = treeList.filter((item) => { + if (title && item.title.indexOf(title) < 0) return false + return true + }) + const pageList = mockList.filter( + (_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1) + ) + return { + code: SUCCESS_CODE, + data: { + total: mockList.length, + list: pageList + } + } + } + }, + // 列表接口 + { + url: '/mock/example/list', + method: 'get', + timeout, + response: ({ query }) => { + const { title, pageIndex, pageSize } = query + const mockList = List.filter((item) => { + if (title && item.title.indexOf(title) < 0) return false + return true + }) + const pageList = mockList.filter( + (_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1) + ) + return { + code: SUCCESS_CODE, + data: { + total: mockList.length, + list: pageList + } + } + } + }, + // 保存接口 + { + url: '/mock/example/save', + method: 'post', + timeout, + response: ({ body }) => { + if (!body.id) { + List = [ + Object.assign(body, { + id: toAnyString() + }) + ].concat(List) + return { + code: SUCCESS_CODE, + data: 'success' + } + } else { + List.map((item) => { + if (item.id === body.id) { + for (const key in item) { + item[key] = body[key] + } + } + }) + return { + code: SUCCESS_CODE, + data: 'success' + } + } + } + }, + // 详情接口 + { + url: '/mock/example/detail', + method: 'get', + response: ({ query }) => { + const { id } = query + for (const example of List) { + if (example.id === id) { + return { + code: SUCCESS_CODE, + data: example + } + } + } + } + }, + // 删除接口 + { + url: '/mock/example/delete', + method: 'post', + response: ({ body }) => { + const ids = body.ids + if (!ids) { + return { + code: 500, + message: '请选择需要删除的数据' + } + } else { + let i = List.length + while (i--) { + if (ids.indexOf(List[i].id) !== -1) { + List.splice(i, 1) + } + } + return { + code: SUCCESS_CODE, + data: 'success' + } + } + } + }, + { + url: '/mock/card/list', + method: 'get', + timeout, + response: ({ query }) => { + const { name, pageIndex, pageSize } = query + const mockList = cardList.filter((item) => { + if (name && item.name.indexOf(name) < 0) return false + return true + }) + const pageList = mockList.filter( + (_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1) + ) + return { + code: SUCCESS_CODE, + data: { + total: mockList.length, + list: pageList + } + } + } + } +] diff --git a/mock/user/index.mock.ts b/mock/user/index.mock.ts new file mode 100644 index 000000000..4e5918cd5 --- /dev/null +++ b/mock/user/index.mock.ts @@ -0,0 +1,90 @@ +import { SUCCESS_CODE } from '@/constants' + +const timeout = 1000 + +const List: { + username: string + password: string + role: string + roleId: string + permissions: string | string[] +}[] = [ + { + username: 'admin', + password: 'admin', + role: 'admin', + roleId: '1', + permissions: ['*.*.*'] + }, + { + username: 'test', + password: 'test', + role: 'test', + roleId: '2', + permissions: ['example:dialog:create', 'example:dialog:delete'] + } +] + +export default [ + // 列表接口 + { + url: '/mock/user/list', + method: 'get', + response: ({ query }) => { + const { username, pageIndex, pageSize } = query + + const mockList = List.filter((item) => { + if (username && item.username.indexOf(username) < 0) return false + return true + }) + const pageList = mockList.filter( + (_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1) + ) + + return { + code: SUCCESS_CODE, + data: { + total: mockList.length, + list: pageList + } + } + } + }, + // 登录接口 + { + url: '/mock/user/login', + method: 'post', + timeout, + response: ({ body }) => { + const data = body + let hasUser = false + for (const user of List) { + if (user.username === data.username && user.password === data.password) { + hasUser = true + return { + code: SUCCESS_CODE, + data: user + } + } + } + if (!hasUser) { + return { + code: 500, + message: '账号或密码错误' + } + } + } + }, + // 退出接口 + { + url: '/mock/user/loginOut', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: null + } + } + } +] diff --git a/mock/workplace/index.mock.ts b/mock/workplace/index.mock.ts new file mode 100644 index 000000000..593ba2749 --- /dev/null +++ b/mock/workplace/index.mock.ts @@ -0,0 +1,169 @@ +import { SUCCESS_CODE } from '@/constants' + +const timeout = 1000 + +export default [ + // 获取统计 + { + url: '/mock/workplace/total', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: { + project: 40, + access: 2340, + todo: 10 + } + } + } + }, + // 获取项目 + { + url: '/mock/workplace/project', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { + name: 'Github', + icon: 'akar-icons:github-fill', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + }, + { + name: 'Vue', + icon: 'logos:vue', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + }, + { + name: 'Angular', + icon: 'logos:angular-icon', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + }, + { + name: 'React', + icon: 'logos:react', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + }, + { + name: 'Webpack', + icon: 'logos:webpack', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + }, + { + name: 'Vite', + icon: 'vscode-icons:file-type-vite', + message: 'workplace.introduction', + personal: 'Archer', + time: new Date() + } + ] + } + } + }, + // 获取动态 + { + url: '/mock/workplace/dynamic', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { + keys: ['workplace.push', 'Github'], + time: new Date() + }, + { + keys: ['workplace.push', 'Github'], + time: new Date() + }, + { + keys: ['workplace.push', 'Github'], + time: new Date() + }, + { + keys: ['workplace.push', 'Github'], + time: new Date() + }, + { + keys: ['workplace.push', 'Github'], + time: new Date() + }, + { + keys: ['workplace.push', 'Github'], + time: new Date() + } + ] + } + } + }, + // 获取团队信息 + { + url: '/mock/workplace/team', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { + name: 'Github', + icon: 'akar-icons:github-fill' + }, + { + name: 'Vue', + icon: 'logos:vue' + }, + { + name: 'Angular', + icon: 'logos:angular-icon' + }, + { + name: 'React', + icon: 'logos:react' + }, + { + name: 'Webpack', + icon: 'logos:webpack' + }, + { + name: 'Vite', + icon: 'vscode-icons:file-type-vite' + } + ] + } + } + }, + // 获取指数 + { + url: '/mock/workplace/radar', + method: 'get', + timeout, + response: () => { + return { + code: SUCCESS_CODE, + data: [ + { name: 'workplace.quote', max: 65, personal: 42, team: 50 }, + { name: 'workplace.contribution', max: 160, personal: 30, team: 140 }, + { name: 'workplace.hot', max: 300, personal: 20, team: 28 }, + { name: 'workplace.yield', max: 130, personal: 35, team: 35 }, + { name: 'workplace.follow', max: 100, personal: 80, team: 90 } + ] + } + } + } +] diff --git a/package.json b/package.json new file mode 100644 index 000000000..29f12f509 --- /dev/null +++ b/package.json @@ -0,0 +1,147 @@ +{ + "name": "vue-element-plus-admin", + "version": "2.8.1", + "description": "一套基于vue3、element-plus、typesScript、vite4的后台集成方案。", + "author": "Archer <502431556@qq.com>", + "private": false, + "type": "module", + "scripts": { + "i": "pnpm install", + "dev": "pnpm vite --mode base", + "ts:check": "pnpm vue-tsc --noEmit --skipLibCheck", + "build:pro": "pnpm vite build --mode pro", + "build:gitee": "pnpm vite build --mode gitee", + "build:dev": "pnpm vite build --mode dev", + "build:test": "pnpm vite build --mode test", + "serve:pro": "pnpm vite preview --mode pro", + "serve:dev": "pnpm vite preview --mode dev", + "serve:test": "pnpm vite preview --mode test", + "npm:check": "pnpx npm-check-updates -u", + "clean": "pnpx rimraf node_modules", + "clean:cache": "pnpx rimraf node_modules/.cache", + "lint:eslint": "eslint . --fix \"src/**/*.{js,ts,tsx,vue,html}\"", + "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,vue,html,md}\"", + "lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", + "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.cjs", + "prepare": "husky install", + "p": "plop", + "icon": "esno ./scripts/icon.ts" + }, + "dependencies": { + "@iconify/iconify": "^3.1.1", + "@iconify/vue": "^4.1.2", + "@vtj/icons": "^0.11.6", + "@vtj/web": "latest", + "@vueuse/core": "^10.11.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.10", + "@zxcvbn-ts/core": "^3.0.4", + "animate.css": "^4.1.1", + "axios": "^1.7.2", + "cropperjs": "^1.6.2", + "dayjs": "^1.11.11", + "driver.js": "^1.3.1", + "echarts": "^5.5.1", + "echarts-wordcloud": "^2.1.0", + "element-plus": "2.7.7", + "lodash-es": "^4.17.21", + "mitt": "^3.0.1", + "monaco-editor": "^0.50.0", + "nprogress": "^0.2.0", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "qrcode": "^1.5.3", + "qs": "^6.12.3", + "url": "^0.11.3", + "vue": "3.4.32", + "vue-draggable-plus": "^0.5.2", + "vue-i18n": "9.13.1", + "vue-json-pretty": "^2.4.0", + "vue-router": "^4.4.0", + "vue-types": "^5.1.3", + "xgplayer": "^3.0.18" + }, + "devDependencies": { + "@commitlint/cli": "^19.3.0", + "@commitlint/config-conventional": "^19.2.2", + "@iconify/json": "^2.2.229", + "@intlify/unplugin-vue-i18n": "^4.0.0", + "@types/fs-extra": "^11.0.4", + "@types/inquirer": "^9.0.7", + "@types/lodash-es": "^4.17.12", + "@types/mockjs": "^1.0.10", + "@types/node": "^20.14.11", + "@types/nprogress": "^0.2.3", + "@types/qrcode": "^1.5.5", + "@types/qs": "^6.9.15", + "@types/sortablejs": "^1.15.8", + "@typescript-eslint/eslint-plugin": "^7.16.1", + "@typescript-eslint/parser": "^7.16.1", + "@unocss/transformer-variant-group": "^0.61.5", + "@vitejs/plugin-legacy": "^5.4.1", + "@vitejs/plugin-vue": "^5.0.5", + "@vitejs/plugin-vue-jsx": "^4.0.0", + "@vtj/cli": "latest", + "@vtj/pro": "latest", + "autoprefixer": "^10.4.19", + "chalk": "^5.3.0", + "consola": "^3.2.3", + "eslint": "^9.7.0", + "eslint-config-prettier": "^9.1.0", + "eslint-define-config": "^2.1.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-vue": "^9.27.0", + "esno": "^4.7.0", + "fs-extra": "^11.2.0", + "husky": "^9.1.0", + "inquirer": "^10.0.3", + "less": "^4.2.0", + "lint-staged": "^15.2.7", + "mockjs": "^1.1.0", + "plop": "^4.0.1", + "postcss": "^8.4.39", + "postcss-html": "^1.7.0", + "postcss-less": "^6.0.0", + "prettier": "^3.3.3", + "rimraf": "^6.0.1", + "rollup": "^4.18.1", + "rollup-plugin-visualizer": "^5.12.0", + "stylelint": "^16.7.0", + "stylelint-config-html": "^1.1.0", + "stylelint-config-recommended": "^14.0.1", + "stylelint-config-standard": "^36.0.1", + "stylelint-order": "^6.0.4", + "terser": "^5.31.3", + "typescript": "5.5.3", + "typescript-eslint": "^7.16.1", + "unocss": "^0.61.5", + "vite": "5.3.4", + "vite-plugin-ejs": "^1.7.0", + "vite-plugin-eslint": "^1.8.1", + "vite-plugin-mock": "2.9.6", + "vite-plugin-progress": "^0.0.7", + "vite-plugin-purge-icons": "^0.10.0", + "vite-plugin-style-import": "2.0.0", + "vite-plugin-svg-icons": "^2.0.1", + "vite-plugin-url-copy": "^1.1.4", + "vue-tsc": "^2.0.26" + }, + "packageManager": "pnpm@8.1.0", + "engines": { + "node": ">=18.0.0", + "pnpm": ">=8.1.0" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/kailong321200875/vue-element-plus-admin.git" + }, + "bugs": { + "url": "https://github.com/kailong321200875/vue-element-plus-admin/issues" + }, + "homepage": "https://github.com/kailong321200875/vue-element-plus-admin", + "vtj": { + "id": "vue-element-plus-admin", + "name": "ElementAdmin" + } +} diff --git a/plop/component/component.hbs b/plop/component/component.hbs new file mode 100644 index 000000000..21e56533d --- /dev/null +++ b/plop/component/component.hbs @@ -0,0 +1,11 @@ + + + diff --git a/plop/component/index.hbs b/plop/component/index.hbs new file mode 100644 index 000000000..aca6f0a8c --- /dev/null +++ b/plop/component/index.hbs @@ -0,0 +1,3 @@ +import {{ upperFirstName }} from './src/{{ upperFirstName }}.vue' + +export { {{ upperFirstName }} } diff --git a/plop/component/prompt.cjs b/plop/component/prompt.cjs new file mode 100644 index 000000000..98a852f07 --- /dev/null +++ b/plop/component/prompt.cjs @@ -0,0 +1,38 @@ +const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1) + +module.exports = { + description: 'Create vue component', + prompts: [ + { + type: 'input', + name: 'name', + message: '请输入组件名称(Please enter the component name)' + } + ], + actions: (data) => { + const { name } = data + const upperFirstName = toUpperCase(name) + + const actions = [] + if (name) { + actions.push({ + type: 'add', + path: `./src/components/${upperFirstName}/src/${upperFirstName}.vue`, + templateFile: './plop/component/component.hbs', + data: { + name, + upperFirstName + } + }, { + type: 'add', + path: `./src/components/${upperFirstName}/index.ts`, + templateFile: './plop/component/index.hbs', + data: { + upperFirstName + } + }) + } + + return actions + } +} diff --git a/plop/view/prompt.cjs b/plop/view/prompt.cjs new file mode 100644 index 000000000..dbf324fb6 --- /dev/null +++ b/plop/view/prompt.cjs @@ -0,0 +1,37 @@ +const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1) + +module.exports = { + description: 'Create vue view', + prompts: [ + { + type: 'input', + name: 'path', + message: '请输入路径(Please enter a path)', + default: 'views' + }, + { + type: 'input', + name: 'name', + message: '请输入模块名称(Please enter module name)' + } + ], + actions: (data) => { + const { name, path } = data + const upperFirstName = toUpperCase(name) + + const actions = [] + if (name) { + actions.push({ + type: 'add', + path: `./src/${path}/${upperFirstName}.vue`, + templateFile: './plop/view/view.hbs', + data: { + name, + upperFirstName + } + }) + } + + return actions + } +} diff --git a/plop/view/view.hbs b/plop/view/view.hbs new file mode 100644 index 000000000..0ae9c154d --- /dev/null +++ b/plop/view/view.hbs @@ -0,0 +1,7 @@ + + + diff --git a/plopfile.cjs b/plopfile.cjs new file mode 100644 index 000000000..ad90fa179 --- /dev/null +++ b/plopfile.cjs @@ -0,0 +1,7 @@ +const viewGenerator = require('./plop/view/prompt.cjs') +const componentGenerator = require('./plop/component/prompt.cjs') + +module.exports = function (plop) { + plop.setGenerator('view', viewGenerator) + plop.setGenerator('component', componentGenerator) +} diff --git a/pnpm b/pnpm new file mode 100644 index 000000000..e69de29bb diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 000000000..961986e2b --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {} + } +} diff --git a/prettier.config.cjs b/prettier.config.cjs new file mode 100644 index 000000000..b46239fe4 --- /dev/null +++ b/prettier.config.cjs @@ -0,0 +1,19 @@ +module.exports = { + printWidth: 100, + tabWidth: 2, + useTabs: false, + semi: false, + vueIndentScriptAndStyle: false, + singleQuote: true, + quoteProps: 'as-needed', + bracketSpacing: true, + trailingComma: 'none', + jsxSingleQuote: false, + arrowParens: 'always', + insertPragma: false, + requirePragma: false, + proseWrap: 'never', + htmlWhitespaceSensitivity: 'strict', + endOfLine: 'auto', + rangeStart: 0 +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 000000000..5a7de0826 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/logo.gif b/public/logo.gif new file mode 100644 index 000000000..fdbd32c67 Binary files /dev/null and b/public/logo.gif differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 000000000..b76c71b6b Binary files /dev/null and b/public/logo.png differ diff --git a/scripts/icon.ts b/scripts/icon.ts new file mode 100644 index 000000000..724342e64 --- /dev/null +++ b/scripts/icon.ts @@ -0,0 +1,73 @@ +import path from 'path' +import fs from 'fs-extra' +import inquirer from 'inquirer' +import chalk from 'chalk' +import pkg from '../package.json' +import { ICON_PREFIX } from '../src/constants' + +interface Icon { + name: string + prefix: string + icons: string[] +} + +async function generateIcon() { + const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json') + + const raw = await fs.readJSON(path.join(dir, 'collections.json')) + + const collections = Object.entries(raw).map(([id, v]) => ({ + ...(v as any), + id + })) + + const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name })) + + inquirer + .prompt([ + // { + // type: 'list', + // name: 'useType', + // choices: [ + // { key: 'local', value: 'local', name: 'Local' }, + // { key: 'onLine', value: 'onLine', name: 'OnLine' } + // ], + // message: 'How to use icons?' + // }, + { + type: 'list', + name: 'iconSet', + choices: choices, + message: 'Select the icon set that needs to be generated?' + } + ]) + // ↓命令行问答的答案 + .then(async (answers) => { + const { iconSet } = answers + // const isOnLine = useType === 'onLine' + const outputDir = path.resolve(process.cwd(), 'src/components/IconPicker/src/data') + fs.ensureDir(outputDir) + const genCollections = collections.filter((item) => [iconSet].includes(item.id)) + const prefixSet: string[] = [] + for (const info of genCollections) { + const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`)) + if (data) { + const { prefix } = data + const prefixName = `${ICON_PREFIX}${prefix}` + const icons = Object.keys(data.icons).map((item) => `${prefixName}:${item}`) + + await fs.writeFileSync( + path.join('src/components/IconPicker/src/data', `icons.${prefix}.ts`), + `export default ${JSON.stringify({ name: info.name, prefix: prefixName, icons })}` + ) + // ↓分类处理完成,push类型名称 + prefixSet.push(prefix) + } + } + console.log( + `✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]` + ) + }) +} + +generateIcon() diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 000000000..57b571f2f --- /dev/null +++ b/src/App.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/api/common/index.ts b/src/api/common/index.ts new file mode 100644 index 000000000..b8c986c56 --- /dev/null +++ b/src/api/common/index.ts @@ -0,0 +1,11 @@ +import request from '@/axios' + +// 获取所有字典 +export const getDictApi = () => { + return request.get({ url: '/mock/dict/list' }) +} + +// 模拟获取某个字典 +export const getDictOneApi = async () => { + return request.get({ url: '/mock/dict/one' }) +} diff --git a/src/api/dashboard/analysis/index.ts b/src/api/dashboard/analysis/index.ts new file mode 100644 index 000000000..f559dc95f --- /dev/null +++ b/src/api/dashboard/analysis/index.ts @@ -0,0 +1,23 @@ +import request from '@/axios' +import type { + AnalysisTotalTypes, + UserAccessSource, + WeeklyUserActivity, + MonthlySales +} from './types' + +export const getCountApi = (): Promise> => { + return request.get({ url: '/mock/analysis/total' }) +} + +export const getUserAccessSourceApi = (): Promise> => { + return request.get({ url: '/mock/analysis/userAccessSource' }) +} + +export const getWeeklyUserActivityApi = (): Promise> => { + return request.get({ url: '/mock/analysis/weeklyUserActivity' }) +} + +export const getMonthlySalesApi = (): Promise> => { + return request.get({ url: '/mock/analysis/monthlySales' }) +} diff --git a/src/api/dashboard/analysis/types.ts b/src/api/dashboard/analysis/types.ts new file mode 100644 index 000000000..4a239f56c --- /dev/null +++ b/src/api/dashboard/analysis/types.ts @@ -0,0 +1,22 @@ +export type AnalysisTotalTypes = { + users: number + messages: number + moneys: number + shoppings: number +} + +export type UserAccessSource = { + value: number + name: string +} + +export type WeeklyUserActivity = { + value: number + name: string +} + +export type MonthlySales = { + name: string + estimate: number + actual: number +} diff --git a/src/api/dashboard/workplace/index.ts b/src/api/dashboard/workplace/index.ts new file mode 100644 index 000000000..062f3513f --- /dev/null +++ b/src/api/dashboard/workplace/index.ts @@ -0,0 +1,22 @@ +import request from '@/axios' +import type { WorkplaceTotal, Project, Dynamic, Team, RadarData } from './types' + +export const getCountApi = (): Promise> => { + return request.get({ url: '/mock/workplace/total' }) +} + +export const getProjectApi = (): Promise> => { + return request.get({ url: '/mock/workplace/project' }) +} + +export const getDynamicApi = (): Promise> => { + return request.get({ url: '/mock/workplace/dynamic' }) +} + +export const getTeamApi = (): Promise> => { + return request.get({ url: '/mock/workplace/team' }) +} + +export const getRadarApi = (): Promise> => { + return request.get({ url: '/mock/workplace/radar' }) +} diff --git a/src/api/dashboard/workplace/types.ts b/src/api/dashboard/workplace/types.ts new file mode 100644 index 000000000..da23e7434 --- /dev/null +++ b/src/api/dashboard/workplace/types.ts @@ -0,0 +1,30 @@ +export type WorkplaceTotal = { + project: number + access: number + todo: number +} + +export type Project = { + name: string + icon: string + message: string + personal: string + time: Date | number | string +} + +export type Dynamic = { + keys: string[] + time: Date | number | string +} + +export type Team = { + name: string + icon: string +} + +export type RadarData = { + personal: number + team: number + max: number + name: string +} diff --git a/src/api/department/index.ts b/src/api/department/index.ts new file mode 100644 index 000000000..eb583ac68 --- /dev/null +++ b/src/api/department/index.ts @@ -0,0 +1,30 @@ +import request from '@/axios' +import { DepartmentListResponse, DepartmentUserParams, DepartmentUserResponse } from './types' + +export const getDepartmentApi = () => { + return request.get({ url: '/mock/department/list' }) +} + +export const getUserByIdApi = (params: DepartmentUserParams) => { + return request.get({ url: '/mock/department/users', params }) +} + +export const deleteUserByIdApi = (ids: string[] | number[]) => { + return request.post({ url: '/mock/department/user/delete', data: { ids } }) +} + +export const saveUserApi = (data: any) => { + return request.post({ url: '/mock/department/user/save', data }) +} + +export const saveDepartmentApi = (data: any) => { + return request.post({ url: '/mock/department/save', data }) +} + +export const deleteDepartmentApi = (ids: string[] | number[]) => { + return request.post({ url: '/mock/department/delete', data: { ids } }) +} + +export const getDepartmentTableApi = (params: any) => { + return request.get({ url: '/mock/department/table/list', params }) +} diff --git a/src/api/department/types.ts b/src/api/department/types.ts new file mode 100644 index 000000000..027a62806 --- /dev/null +++ b/src/api/department/types.ts @@ -0,0 +1,32 @@ +export interface DepartmentItem { + id: string + departmentName: string + children?: DepartmentItem[] +} + +export interface DepartmentListResponse { + list: DepartmentItem[] +} + +export interface DepartmentUserParams { + pageSize: number + pageIndex: number + id: string + username?: string + account?: string +} + +export interface DepartmentUserItem { + id: string + username: string + account: string + email: string + createTime: string + role: string + department: DepartmentItem +} + +export interface DepartmentUserResponse { + list: DepartmentUserItem[] + total: number +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 000000000..4116d4789 --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,86 @@ +import request from '@/axios' +import { getRefreshToken } from '@/utils/auth' +import type { UserVO, UserLoginVO, RegisterVO } from './types' + +export interface SmsCodeVO { + mobile: string + scene: number +} + +export interface SmsLoginVO { + mobile: string + code: string +} + +// 登录 +export const login = (data: UserLoginVO) => { + return request.post({ url: '/system/auth/login', data }) +} + +// 注册 +export const register = (data: RegisterVO) => { + return request.post({ url: '/system/auth/register', data }) +} + +// 使用租户名,获得租户编号 +export const getTenantIdByName = (name: string) => { + return request.get({ url: '/system/tenant/get-id-by-name?name=' + name }) +} + +// 使用租户域名,获得租户信息 +export const getTenantByWebsite = (website: string) => { + return request.get({ url: '/system/tenant/get-by-website?website=' + website }) +} + +// 登出 +export const loginOutApi = () => { + return request.post({ url: '/system/auth/logout' }) +} + +// 获取用户权限信息 +export const getInfo = () => { + return request.get({ url: '/system/auth/get-permission-info' }) +} + +//获取登录验证码 +export const sendSmsCode = (data: SmsCodeVO) => { + return request.post({ url: '/system/auth/send-sms-code', data }) +} + +// 短信验证码登录 +export const smsLogin = (data: SmsLoginVO) => { + return request.post({ url: '/system/auth/sms-login', data }) +} + +// 社交快捷登录,使用 code 授权码 +export function socialLogin(type: string, code: string, state: string) { + return request.post({ + url: '/system/auth/social-login', + data: { + type, + code, + state + } + }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type: number, redirectUri: string) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} +// 获取验证图片以及 token +export const getCode = (data: any) => { + return request.post({ url: '/system/captcha/get', data }) +} + +// 滑动或者点选验证 +export const reqCheck = (data: any) => { + return request.post({ url: '/system/captcha/check', data }) +} + +// 通过短信重置密码 +export const smsResetPassword = (data: any) => { + return request.post({ url: '/system/auth/reset-password', data }) +} diff --git a/src/api/login/types.ts b/src/api/login/types.ts new file mode 100644 index 000000000..4491dc404 --- /dev/null +++ b/src/api/login/types.ts @@ -0,0 +1,39 @@ +export type UserLoginVO = { + username: string + password: string + captchaVerification: string + rememberMe?: boolean + socialType?: string + socialCode?: string + socialState?: string +} + +export type TokenType = { + id: number // 编号 + accessToken: string // 访问令牌 + refreshToken: string // 刷新令牌 + userId: number // 用户编号 + userType: number //用户类型 + clientId: string //客户端编号 + expiresTime: number //过期时间 +} + +export type UserVO = { + id: number + username: string + nickname: string + deptId: number + email: string + mobile: string + sex: number + avatar: string + loginIp: string + loginDate: string +} + +export type RegisterVO = { + tenantName: string + username: string + password: string + captchaVerification: string +} diff --git a/src/api/menu/index.ts b/src/api/menu/index.ts new file mode 100644 index 000000000..a2b934cd1 --- /dev/null +++ b/src/api/menu/index.ts @@ -0,0 +1,5 @@ +import request from '@/axios' + +export const getMenuListApi = () => { + return request.get({ url: '/mock/menu/list' }) +} diff --git a/src/api/request/index.ts b/src/api/request/index.ts new file mode 100644 index 000000000..207f9131e --- /dev/null +++ b/src/api/request/index.ts @@ -0,0 +1,38 @@ +import request from '@/axios' +import { RequestResponse } from './types' + +export const request1 = () => { + return request.get>({ + url: '/mock/request/1' + }) +} + +export const request2 = () => { + return request.get>({ + url: '/mock/request/2' + }) +} + +export const request3 = () => { + return request.get>({ + url: '/mock/request/3' + }) +} + +export const request4 = () => { + return request.get>({ + url: '/mock/request/4' + }) +} + +export const request5 = () => { + return request.get>({ + url: '/mock/request/5' + }) +} + +export const expired = () => { + return request.get>({ + url: '/mock/request/expired' + }) +} diff --git a/src/api/request/types.ts b/src/api/request/types.ts new file mode 100644 index 000000000..9a2063f56 --- /dev/null +++ b/src/api/request/types.ts @@ -0,0 +1,3 @@ +export interface RequestResponse { + data: string +} diff --git a/src/api/role/index.ts b/src/api/role/index.ts new file mode 100644 index 000000000..ecbf9d98a --- /dev/null +++ b/src/api/role/index.ts @@ -0,0 +1,5 @@ +import request from '@/axios' + +export const getRoleListApi = () => { + return request.get({ url: '/mock/role/table' }) +} diff --git a/src/api/table/index.ts b/src/api/table/index.ts new file mode 100644 index 000000000..c870f2526 --- /dev/null +++ b/src/api/table/index.ts @@ -0,0 +1,26 @@ +import request from '@/axios' +import type { TableData } from './types' + +export const getTableListApi = (params: any) => { + return request.get({ url: '/mock/example/list', params }) +} + +export const getCardTableListApi = (params: any) => { + return request.get({ url: '/mock/card/list', params }) +} + +export const getTreeTableListApi = (params: any) => { + return request.get({ url: '/mock/example/treeList', params }) +} + +export const saveTableApi = (data: Partial): Promise => { + return request.post({ url: '/mock/example/save', data }) +} + +export const getTableDetApi = (id: string): Promise> => { + return request.get({ url: '/mock/example/detail', params: { id } }) +} + +export const delTableListApi = (ids: string[] | number[]): Promise => { + return request.post({ url: '/mock/example/delete', data: { ids } }) +} diff --git a/src/api/table/types.ts b/src/api/table/types.ts new file mode 100644 index 000000000..876c11165 --- /dev/null +++ b/src/api/table/types.ts @@ -0,0 +1,9 @@ +export type TableData = { + id: string + author: string + title: string + content: string + importance: number + display_time: string + pageviews: number +} diff --git a/src/assets/imgs/avatar.jpg b/src/assets/imgs/avatar.jpg new file mode 100644 index 000000000..d46a70a46 Binary files /dev/null and b/src/assets/imgs/avatar.jpg differ diff --git a/src/assets/imgs/logo.png b/src/assets/imgs/logo.png new file mode 100644 index 000000000..b76c71b6b Binary files /dev/null and b/src/assets/imgs/logo.png differ diff --git a/src/assets/imgs/personal-center-bg.jpg b/src/assets/imgs/personal-center-bg.jpg new file mode 100644 index 000000000..b8ce80b94 Binary files /dev/null and b/src/assets/imgs/personal-center-bg.jpg differ diff --git a/src/assets/svgs/403.svg b/src/assets/svgs/403.svg new file mode 100644 index 000000000..450059617 --- /dev/null +++ b/src/assets/svgs/403.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/404.svg b/src/assets/svgs/404.svg new file mode 100644 index 000000000..5244d8d4d --- /dev/null +++ b/src/assets/svgs/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/500.svg b/src/assets/svgs/500.svg new file mode 100644 index 000000000..9c020927f --- /dev/null +++ b/src/assets/svgs/500.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/icon.svg b/src/assets/svgs/icon.svg new file mode 100644 index 000000000..7024becf5 --- /dev/null +++ b/src/assets/svgs/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/login-bg.svg b/src/assets/svgs/login-bg.svg new file mode 100644 index 000000000..bbe06c160 --- /dev/null +++ b/src/assets/svgs/login-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/login-box-bg.svg b/src/assets/svgs/login-box-bg.svg new file mode 100644 index 000000000..ab1004030 --- /dev/null +++ b/src/assets/svgs/login-box-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/message.svg b/src/assets/svgs/message.svg new file mode 100644 index 000000000..14ca81728 --- /dev/null +++ b/src/assets/svgs/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/money.svg b/src/assets/svgs/money.svg new file mode 100644 index 000000000..c1580de10 --- /dev/null +++ b/src/assets/svgs/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/peoples.svg b/src/assets/svgs/peoples.svg new file mode 100644 index 000000000..aab852e52 --- /dev/null +++ b/src/assets/svgs/peoples.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/shopping.svg b/src/assets/svgs/shopping.svg new file mode 100644 index 000000000..f395bc7f6 --- /dev/null +++ b/src/assets/svgs/shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/axios/config.ts b/src/axios/config.ts new file mode 100644 index 000000000..c99e99a11 --- /dev/null +++ b/src/axios/config.ts @@ -0,0 +1,78 @@ +import { AxiosResponse, InternalAxiosRequestConfig } from './types' +import { ElMessage } from 'element-plus' +import qs from 'qs' +import { SUCCESS_CODE, TRANSFORM_REQUEST_DATA } from '@/constants' +import { useUserStoreWithOut } from '@/store/modules/user' +import { objToFormData } from '@/utils' +import { getTenantId } from '@/utils/auth' + +const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => { + // 添加租户ID请求头 + const tenantId = getTenantId() + if (tenantId) { + config.headers['Tenant-Id'] = tenantId + } + if ( + config.method === 'post' && + config.headers['Content-Type'] === 'application/x-www-form-urlencoded' + ) { + config.data = qs.stringify(config.data) + } else if ( + TRANSFORM_REQUEST_DATA && + config.method === 'post' && + config.headers['Content-Type'] === 'multipart/form-data' && + !(config.data instanceof FormData) + ) { + config.data = objToFormData(config.data) + } + if (config.method === 'get' && config.params) { + let url = config.url as string + url += '?' + const keys = Object.keys(config.params) + for (const key of keys) { + if (config.params[key] !== void 0 && config.params[key] !== null) { + url += `${key}=${encodeURIComponent(config.params[key])}&` + } + } + url = url.substring(0, url.length - 1) + config.params = {} + config.url = url + } + return config +} + +const defaultResponseInterceptors = (response: AxiosResponse) => { + // 添加调试日志 + console.log('响应URL:', response.config.url); + console.log('响应状态:', response.status); + console.log('响应数据类型:', typeof response.data); + + // 验证码接口特殊处理 + if (response.config.url?.includes('/system/captcha')) { + console.log('验证码接口响应:', response.data); + return response.data; + } + + if (response?.config?.responseType === 'blob') { + // 如果是文件流,直接过 + return response + } else if (response.data.code === SUCCESS_CODE) { + return response.data + } else { + // 添加更详细的错误日志 + console.error('响应错误:', response.data); + console.error('错误代码:', response.data.code); + console.error('错误消息:', response.data.message); + + ElMessage.error(response?.data?.message || '请求失败') + if (response?.data?.code === 401) { + const userStore = useUserStoreWithOut() + userStore.logout() + } + + // 返回响应数据,让调用方处理错误 + return response.data; + } +} + +export { defaultResponseInterceptors, defaultRequestInterceptors } diff --git a/src/axios/index.ts b/src/axios/index.ts new file mode 100644 index 000000000..60b46c0a8 --- /dev/null +++ b/src/axios/index.ts @@ -0,0 +1,42 @@ +import service from './service' +import { CONTENT_TYPE } from '@/constants' +import { useUserStoreWithOut } from '@/store/modules/user' + +const request = (option: AxiosConfig) => { + const { url, method, params, data, headers, responseType } = option + + const userStore = useUserStoreWithOut() + return service.request({ + url: url, + method, + params, + data: data, + responseType: responseType, + headers: { + 'Content-Type': CONTENT_TYPE, + [userStore.getTokenKey ?? 'Authorization']: userStore.getToken ?? '', + ...headers + } + }) +} + +export default { + get: (option: AxiosConfig) => { + return request({ method: 'get', ...option }) as Promise> + }, + post: (option: AxiosConfig) => { + return request({ method: 'post', ...option }) as Promise> + }, + delete: (option: AxiosConfig) => { + return request({ method: 'delete', ...option }) as Promise> + }, + put: (option: AxiosConfig) => { + return request({ method: 'put', ...option }) as Promise> + }, + cancelRequest: (url: string | string[]) => { + return service.cancelRequest(url) + }, + cancelAllRequest: () => { + return service.cancelAllRequest() + } +} diff --git a/src/axios/service.ts b/src/axios/service.ts new file mode 100644 index 000000000..a392522c0 --- /dev/null +++ b/src/axios/service.ts @@ -0,0 +1,77 @@ +import axios, { AxiosError } from 'axios' +import { defaultRequestInterceptors, defaultResponseInterceptors } from './config' + +import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './types' +import { ElMessage } from 'element-plus' +import { REQUEST_TIMEOUT } from '@/constants' + +export const PATH_URL = import.meta.env.VITE_API_BASE_PATH + +const abortControllerMap: Map = new Map() + +const axiosInstance: AxiosInstance = axios.create({ + timeout: REQUEST_TIMEOUT, + baseURL: PATH_URL +}) + +axiosInstance.interceptors.request.use((res: InternalAxiosRequestConfig) => { + const controller = new AbortController() + const url = res.url || '' + res.signal = controller.signal + abortControllerMap.set( + import.meta.env.VITE_USE_MOCK === 'true' ? url.replace('/mock', '') : url, + controller + ) + return res +}) + +axiosInstance.interceptors.response.use( + (res: AxiosResponse) => { + const url = res.config.url || '' + abortControllerMap.delete(url) + // 这里不能做任何处理,否则后面的 interceptors 拿不到完整的上下文了 + return res + }, + (error: AxiosError) => { + console.log('err: ' + error) // for debug + ElMessage.error(error.message) + return Promise.reject(error) + } +) + +axiosInstance.interceptors.request.use(defaultRequestInterceptors) +axiosInstance.interceptors.response.use(defaultResponseInterceptors) + +const service = { + request: (config: RequestConfig) => { + return new Promise((resolve, reject) => { + if (config.interceptors?.requestInterceptors) { + config = config.interceptors.requestInterceptors(config as any) + } + + axiosInstance + .request(config) + .then((res) => { + resolve(res) + }) + .catch((err: any) => { + reject(err) + }) + }) + }, + cancelRequest: (url: string | string[]) => { + const urlList = Array.isArray(url) ? url : [url] + for (const _url of urlList) { + abortControllerMap.get(_url)?.abort() + abortControllerMap.delete(_url) + } + }, + cancelAllRequest() { + for (const [_, controller] of abortControllerMap) { + controller.abort() + } + abortControllerMap.clear() + } +} + +export default service diff --git a/src/axios/types/index.ts b/src/axios/types/index.ts new file mode 100644 index 000000000..b70eb266c --- /dev/null +++ b/src/axios/types/index.ts @@ -0,0 +1,31 @@ +import type { + InternalAxiosRequestConfig, + AxiosResponse, + AxiosRequestConfig, + AxiosInstance, + AxiosRequestHeaders, + AxiosError +} from 'axios' + +interface RequestInterceptors { + // 请求拦截 + requestInterceptors?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig + requestInterceptorsCatch?: (err: any) => any + // 响应拦截 + responseInterceptors?: (config: T) => T + responseInterceptorsCatch?: (err: any) => any +} + +interface RequestConfig extends AxiosRequestConfig { + interceptors?: RequestInterceptors +} + +export { + AxiosResponse, + RequestInterceptors, + RequestConfig, + AxiosInstance, + InternalAxiosRequestConfig, + AxiosRequestHeaders, + AxiosError +} diff --git a/src/components/Avatars/index.ts b/src/components/Avatars/index.ts new file mode 100644 index 000000000..5eaa329f3 --- /dev/null +++ b/src/components/Avatars/index.ts @@ -0,0 +1,4 @@ +import Avatars from './src/Avatars.vue' + +export type { AvatarItem } from './src/types' +export { Avatars } diff --git a/src/components/Avatars/src/Avatars.vue b/src/components/Avatars/src/Avatars.vue new file mode 100644 index 000000000..1f3619c18 --- /dev/null +++ b/src/components/Avatars/src/Avatars.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/components/Avatars/src/types/index.ts b/src/components/Avatars/src/types/index.ts new file mode 100644 index 000000000..c2554ee3e --- /dev/null +++ b/src/components/Avatars/src/types/index.ts @@ -0,0 +1,4 @@ +export interface AvatarItem { + url: string + name?: string +} diff --git a/src/components/Backtop/index.ts b/src/components/Backtop/index.ts new file mode 100644 index 000000000..96de88d69 --- /dev/null +++ b/src/components/Backtop/index.ts @@ -0,0 +1,3 @@ +import Backtop from './src/Backtop.vue' + +export { Backtop } diff --git a/src/components/Backtop/src/Backtop.vue b/src/components/Backtop/src/Backtop.vue new file mode 100644 index 000000000..461901793 --- /dev/null +++ b/src/components/Backtop/src/Backtop.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/Breadcrumb/index.ts b/src/components/Breadcrumb/index.ts new file mode 100644 index 000000000..93ffe7054 --- /dev/null +++ b/src/components/Breadcrumb/index.ts @@ -0,0 +1,3 @@ +import Breadcrumb from './src/Breadcrumb.vue' + +export { Breadcrumb } diff --git a/src/components/Breadcrumb/src/Breadcrumb.vue b/src/components/Breadcrumb/src/Breadcrumb.vue new file mode 100644 index 000000000..cc79f1b12 --- /dev/null +++ b/src/components/Breadcrumb/src/Breadcrumb.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/components/Breadcrumb/src/helper.ts b/src/components/Breadcrumb/src/helper.ts new file mode 100644 index 000000000..690cff982 --- /dev/null +++ b/src/components/Breadcrumb/src/helper.ts @@ -0,0 +1,30 @@ +import { pathResolve } from '@/utils/routerHelper' + +export const filterBreadcrumb = ( + routes: AppRouteRecordRaw[], + parentPath = '' +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + + for (const route of routes) { + const meta = route?.meta + if (meta.hidden && !meta.canTo) { + continue + } + + const data: AppRouteRecordRaw = + !meta.alwaysShow && route.children?.length === 1 + ? { ...route.children[0], path: pathResolve(route.path, route.children[0].path) } + : { ...route } + + data.path = pathResolve(parentPath, data.path) + + if (data.children) { + data.children = filterBreadcrumb(data.children, data.path) + } + if (data) { + res.push(data) + } + } + return res +} diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts new file mode 100644 index 000000000..6ae43b102 --- /dev/null +++ b/src/components/Button/index.ts @@ -0,0 +1,3 @@ +import BaseButton from './src/Button.vue' + +export { BaseButton } diff --git a/src/components/Button/src/Button.vue b/src/components/Button/src/Button.vue new file mode 100644 index 000000000..c20028c39 --- /dev/null +++ b/src/components/Button/src/Button.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/components/CodeEditor/index.ts b/src/components/CodeEditor/index.ts new file mode 100644 index 000000000..5bf3e9ef7 --- /dev/null +++ b/src/components/CodeEditor/index.ts @@ -0,0 +1,3 @@ +import CodeEditor from './src/CodeEditor.vue' + +export { CodeEditor } diff --git a/src/components/CodeEditor/src/CodeEditor.vue b/src/components/CodeEditor/src/CodeEditor.vue new file mode 100644 index 000000000..306db1341 --- /dev/null +++ b/src/components/CodeEditor/src/CodeEditor.vue @@ -0,0 +1,119 @@ + + + diff --git a/src/components/CodeEditor/src/config/config.ts b/src/components/CodeEditor/src/config/config.ts new file mode 100644 index 000000000..4fa7b307f --- /dev/null +++ b/src/components/CodeEditor/src/config/config.ts @@ -0,0 +1,129 @@ +export const languageOptions = [ + { label: 'plaintext', value: 'plaintext' }, + { label: 'abap', value: 'abap' }, + { label: 'apex', value: 'apex' }, + { label: 'azcli', value: 'azcli' }, + { label: 'bat', value: 'bat' }, + { label: 'bicep', value: 'bicep' }, + { label: 'cameligo', value: 'cameligo' }, + { label: 'clojure', value: 'clojure' }, + { label: 'coffeescript', value: 'coffeescript' }, + { label: 'c', value: 'c' }, + { label: 'cpp', value: 'cpp' }, + { label: 'csharp', value: 'csharp' }, + { label: 'csp', value: 'csp' }, + { label: 'css', value: 'css' }, + { label: 'cypher', value: 'cypher' }, + { label: 'dart', value: 'dart' }, + { label: 'dockerfile', value: 'dockerfile' }, + { label: 'ecl', value: 'ecl' }, + { label: 'elixir', value: 'elixir' }, + { label: 'flow9', value: 'flow9' }, + { label: 'fsharp', value: 'fsharp' }, + { label: 'freemarker2', value: 'freemarker2' }, + { + label: 'freemarker2.tag-angle.interpolation-dollar', + value: 'freemarker2.tag-angle.interpolation-dollar' + }, + { + label: 'freemarker2.tag-bracket.interpolation-dollar', + value: 'freemarker2.tag-bracket.interpolation-dollar' + }, + { + label: 'freemarker2.tag-angle.interpolation-bracket', + value: 'freemarker2.tag-angle.interpolation-bracket' + }, + { + label: 'freemarker2.tag-bracket.interpolation-bracket', + value: 'freemarker2.tag-bracket.interpolation-bracket' + }, + { + label: 'freemarker2.tag-auto.interpolation-dollar', + value: 'freemarker2.tag-auto.interpolation-dollar' + }, + { + label: 'freemarker2.tag-auto.interpolation-bracket', + value: 'freemarker2.tag-auto.interpolation-bracket' + }, + { label: 'go', value: 'go' }, + { label: 'graphql', value: 'graphql' }, + { label: 'handlebars', value: 'handlebars' }, + { label: 'hcl', value: 'hcl' }, + { label: 'html', value: 'html' }, + { label: 'ini', value: 'ini' }, + { label: 'java', value: 'java' }, + { label: 'javascript', value: 'javascript' }, + { label: 'julia', value: 'julia' }, + { label: 'kotlin', value: 'kotlin' }, + { label: 'less', value: 'less' }, + { label: 'lexon', value: 'lexon' }, + { label: 'lua', value: 'lua' }, + { label: 'liquid', value: 'liquid' }, + { label: 'm3', value: 'm3' }, + { label: 'markdown', value: 'markdown' }, + { label: 'mdx', value: 'mdx' }, + { label: 'mips', value: 'mips' }, + { label: 'msdax', value: 'msdax' }, + { label: 'mysql', value: 'mysql' }, + { label: 'objective-c', value: 'objective-c' }, + { label: 'pascal', value: 'pascal' }, + { label: 'pascaligo', value: 'pascaligo' }, + { label: 'perl', value: 'perl' }, + { label: 'pgsql', value: 'pgsql' }, + { label: 'php', value: 'php' }, + { label: 'pla', value: 'pla' }, + { label: 'postiats', value: 'postiats' }, + { label: 'powerquery', value: 'powerquery' }, + { label: 'powershell', value: 'powershell' }, + { label: 'proto', value: 'proto' }, + { label: 'pug', value: 'pug' }, + { label: 'python', value: 'python' }, + { label: 'qsharp', value: 'qsharp' }, + { label: 'r', value: 'r' }, + { label: 'razor', value: 'razor' }, + { label: 'redis', value: 'redis' }, + { label: 'redshift', value: 'redshift' }, + { label: 'restructuredtext', value: 'restructuredtext' }, + { label: 'ruby', value: 'ruby' }, + { label: 'rust', value: 'rust' }, + { label: 'sb', value: 'sb' }, + { label: 'scala', value: 'scala' }, + { label: 'scheme', value: 'scheme' }, + { label: 'scss', value: 'scss' }, + { label: 'shell', value: 'shell' }, + { label: 'sol', value: 'sol' }, + { label: 'aes', value: 'aes' }, + { label: 'sparql', value: 'sparql' }, + { label: 'sql', value: 'sql' }, + { label: 'st', value: 'st' }, + { label: 'swift', value: 'swift' }, + { label: 'systemverilog', value: 'systemverilog' }, + { label: 'verilog', value: 'verilog' }, + { label: 'tcl', value: 'tcl' }, + { label: 'twig', value: 'twig' }, + { label: 'typescript', value: 'typescript' }, + { label: 'vb', value: 'vb' }, + { label: 'wgsl', value: 'wgsl' }, + { label: 'xml', value: 'xml' }, + { label: 'yaml', value: 'yaml' }, + { label: 'json', value: 'json' } +] + +export const themeOptions = [ + { + label: 'vs', + value: 'vs' + }, + { + label: 'vs-dark', + value: 'vs-dark' + }, + { + label: 'hc-black', + value: 'hc-black' + }, + { + label: 'hc-light', + value: 'hc-light' + } +] diff --git a/src/components/Collapse/index.ts b/src/components/Collapse/index.ts new file mode 100644 index 000000000..73f65a3a6 --- /dev/null +++ b/src/components/Collapse/index.ts @@ -0,0 +1,3 @@ +import Collapse from './src/Collapse.vue' + +export { Collapse } diff --git a/src/components/Collapse/src/Collapse.vue b/src/components/Collapse/src/Collapse.vue new file mode 100644 index 000000000..542d9d396 --- /dev/null +++ b/src/components/Collapse/src/Collapse.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/ConfigGlobal/index.ts b/src/components/ConfigGlobal/index.ts new file mode 100644 index 000000000..eaeb7d064 --- /dev/null +++ b/src/components/ConfigGlobal/index.ts @@ -0,0 +1,5 @@ +import ConfigGlobal from './src/ConfigGlobal.vue' + +export type { ConfigGlobalTypes } from './src/types' + +export { ConfigGlobal } diff --git a/src/components/ConfigGlobal/src/ConfigGlobal.vue b/src/components/ConfigGlobal/src/ConfigGlobal.vue new file mode 100644 index 000000000..5bd90cf1e --- /dev/null +++ b/src/components/ConfigGlobal/src/ConfigGlobal.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/components/ConfigGlobal/src/types/index.ts b/src/components/ConfigGlobal/src/types/index.ts new file mode 100644 index 000000000..d41e4d351 --- /dev/null +++ b/src/components/ConfigGlobal/src/types/index.ts @@ -0,0 +1,5 @@ +import { ComponentSize } from 'element-plus' + +export interface ConfigGlobalTypes { + size?: ComponentSize +} diff --git a/src/components/ContentDetailWrap/index.ts b/src/components/ContentDetailWrap/index.ts new file mode 100644 index 000000000..1871cac72 --- /dev/null +++ b/src/components/ContentDetailWrap/index.ts @@ -0,0 +1,3 @@ +import ContentDetailWrap from './src/ContentDetailWrap.vue' + +export { ContentDetailWrap } diff --git a/src/components/ContentDetailWrap/src/ContentDetailWrap.vue b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue new file mode 100644 index 000000000..29b4ff703 --- /dev/null +++ b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/ContentWrap/index.ts b/src/components/ContentWrap/index.ts new file mode 100644 index 000000000..8c22cc833 --- /dev/null +++ b/src/components/ContentWrap/index.ts @@ -0,0 +1,3 @@ +import ContentWrap from './src/ContentWrap.vue' + +export { ContentWrap } diff --git a/src/components/ContentWrap/src/ContentWrap.vue b/src/components/ContentWrap/src/ContentWrap.vue new file mode 100644 index 000000000..8557e8126 --- /dev/null +++ b/src/components/ContentWrap/src/ContentWrap.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/ContextMenu/index.ts b/src/components/ContextMenu/index.ts new file mode 100644 index 000000000..1b5442d9b --- /dev/null +++ b/src/components/ContextMenu/index.ts @@ -0,0 +1,12 @@ +import ContextMenu from './src/ContextMenu.vue' +import { ElDropdown } from 'element-plus' +import type { RouteLocationNormalizedLoaded } from 'vue-router' + +export type { ContextMenuSchema } from './src/types' + +export interface ContextMenuExpose { + elDropdownMenuRef: ComponentRef + tagItem: RouteLocationNormalizedLoaded +} + +export { ContextMenu } diff --git a/src/components/ContextMenu/src/ContextMenu.vue b/src/components/ContextMenu/src/ContextMenu.vue new file mode 100644 index 000000000..95830373d --- /dev/null +++ b/src/components/ContextMenu/src/ContextMenu.vue @@ -0,0 +1,72 @@ + + + diff --git a/src/components/ContextMenu/src/types/index.ts b/src/components/ContextMenu/src/types/index.ts new file mode 100644 index 000000000..b2be72ba6 --- /dev/null +++ b/src/components/ContextMenu/src/types/index.ts @@ -0,0 +1,7 @@ +export interface ContextMenuSchema { + disabled?: boolean + divided?: boolean + icon?: string + label: string + command?: (item: ContextMenuSchema) => void +} diff --git a/src/components/CountTo/index.ts b/src/components/CountTo/index.ts new file mode 100644 index 000000000..2119f0235 --- /dev/null +++ b/src/components/CountTo/index.ts @@ -0,0 +1,3 @@ +import CountTo from './src/CountTo.vue' + +export { CountTo } diff --git a/src/components/CountTo/src/CountTo.vue b/src/components/CountTo/src/CountTo.vue new file mode 100644 index 000000000..cab8ea965 --- /dev/null +++ b/src/components/CountTo/src/CountTo.vue @@ -0,0 +1,180 @@ + + + diff --git a/src/components/Descriptions/index.ts b/src/components/Descriptions/index.ts new file mode 100644 index 000000000..8f9a0f0ba --- /dev/null +++ b/src/components/Descriptions/index.ts @@ -0,0 +1,5 @@ +import Descriptions from './src/Descriptions.vue' + +export type { DescriptionsSchema } from './src/types' + +export { Descriptions } diff --git a/src/components/Descriptions/src/Descriptions.vue b/src/components/Descriptions/src/Descriptions.vue new file mode 100644 index 000000000..a4b222ba8 --- /dev/null +++ b/src/components/Descriptions/src/Descriptions.vue @@ -0,0 +1,197 @@ + + + diff --git a/src/components/Descriptions/src/types/index.ts b/src/components/Descriptions/src/types/index.ts new file mode 100644 index 000000000..be55b1cb0 --- /dev/null +++ b/src/components/Descriptions/src/types/index.ts @@ -0,0 +1,15 @@ +export interface DescriptionsSchema { + span?: number // 占多少分 + field: string // 字段名 + label?: string // label名 + width?: string | number + minWidth?: string | number + align?: 'left' | 'center' | 'right' + labelAlign?: 'left' | 'center' | 'right' + className?: string + labelClassName?: string + slots?: { + default?: (...args: any[]) => JSX.Element | null + label?: (...args: any[]) => JSX.Element | null + } +} diff --git a/src/components/Dialog/hooks/useResize.ts b/src/components/Dialog/hooks/useResize.ts new file mode 100644 index 000000000..d52b279b6 --- /dev/null +++ b/src/components/Dialog/hooks/useResize.ts @@ -0,0 +1,178 @@ +import { ref } from 'vue' + +export const useResize = (props?: { + minHeightPx?: number + minWidthPx?: number + initHeight?: number + initWidth?: number +}) => { + const { + minHeightPx = 400, + minWidthPx = window.innerWidth / 2, + initHeight = 400, + initWidth = window.innerWidth / 2 + } = props || {} + // 屏幕宽度的 50% 作为最小宽度 + // const minWidthPx = window.innerWidth / 2 + // 固定的最小高度 400px + // const minHeightPx = 400 + // 初始高度限制为 400px + const maxHeight = ref(initHeight + 'px') + // 初始宽度限制为 50% + const minWidth = ref(initWidth + 'px') + const setupDrag = (elDialog: any, el: any) => { + // 获取对话框元素 + // 是否正在调整大小的标志 + let isResizing = false + // 当前调整的方向 + let currentResizeDirection = '' + + // 鼠标移动时的事件处理器,用于检测鼠标位置并设置相应的光标样式 + const handleMouseMove = (e: any) => { + const rect = elDialog.getBoundingClientRect() + // 鼠标相对于对话框左侧的偏移量 + const offsetX = e.clientX - rect.left + // 鼠标相对于对话框顶部的偏移量 + const offsetY = e.clientY - rect.top + const width = elDialog.clientWidth + const height = elDialog.clientHeight + + // 获取对话框的内边距 + const computedStyle = window.getComputedStyle(elDialog) + const paddingLeft = parseFloat(computedStyle.paddingLeft) + const paddingRight = parseFloat(computedStyle.paddingRight) + const paddingBottom = parseFloat(computedStyle.paddingBottom) + const paddingTop = parseFloat(computedStyle.paddingTop) + + // 根据鼠标位置设置相应的光标样式和调整方向 + if (!isResizing) { + if (offsetX < paddingLeft && offsetY > paddingTop && offsetY < height - paddingBottom) { + elDialog.style.cursor = 'ew-resize' // 左右箭头 + currentResizeDirection = 'left' + } else if ( + offsetX > width - paddingRight && + offsetY > paddingTop && + offsetY < height - paddingBottom + ) { + elDialog.style.cursor = 'ew-resize' // 左右箭头 + currentResizeDirection = 'right' + } else if ( + offsetY < paddingTop && + offsetX > paddingLeft && + offsetX < width - paddingRight + ) { + elDialog.style.cursor = 'ns-resize' // 上下箭头 + currentResizeDirection = 'top' + } else if ( + offsetY > height - paddingBottom && + offsetX > paddingLeft && + offsetX < width - paddingRight + ) { + elDialog.style.cursor = 'ns-resize' // 上下箭头 + currentResizeDirection = 'bottom' + } else if (offsetX < paddingLeft && offsetY < paddingTop) { + elDialog.style.cursor = 'nwse-resize' // 左上右下箭头 + currentResizeDirection = 'top-left' + } else if (offsetX > width - paddingRight && offsetY < paddingTop) { + elDialog.style.cursor = 'nesw-resize' // 右上左下箭头 + currentResizeDirection = 'top-right' + } else if (offsetX < paddingLeft && offsetY > height - paddingBottom) { + elDialog.style.cursor = 'nesw-resize' // 右上左下箭头 + currentResizeDirection = 'bottom-left' + } else if (offsetX > width - paddingRight && offsetY > height - paddingBottom) { + elDialog.style.cursor = 'nwse-resize' // 左上右下箭头 + currentResizeDirection = 'bottom-right' + } else { + elDialog.style.cursor = 'default' + currentResizeDirection = '' + } + } + } + + // 鼠标按下时的事件处理器,开始调整对话框大小 + const handleMouseDown = (e) => { + if (currentResizeDirection) { + isResizing = true + + const initialX = e.clientX + const initialY = e.clientY + const initialWidth = elDialog.clientWidth + const initialHeight = el.querySelector('.el-dialog__body').clientHeight + + // 调整大小的事件处理器 + const handleResizing = (e: any) => { + if (!isResizing) return + + let newWidth = initialWidth + let newHeight = initialHeight + + // 根据当前调整方向计算新的宽度和高度 + if (currentResizeDirection.includes('right')) { + newWidth = Math.max(minWidthPx, initialWidth + (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + } + + if (currentResizeDirection.includes('left')) { + newWidth = Math.max(minWidthPx, initialWidth - (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + } + + if (currentResizeDirection.includes('bottom')) { + newHeight = Math.max(minHeightPx, initialHeight + (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + + if (currentResizeDirection.includes('top')) { + newHeight = Math.max(minHeightPx, initialHeight - (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + + if (currentResizeDirection === 'top-left') { + newWidth = Math.max(minWidthPx, initialWidth - (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + newHeight = Math.max(minHeightPx, initialHeight - (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + + if (currentResizeDirection === 'top-right') { + newWidth = Math.max(minWidthPx, initialWidth + (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + newHeight = Math.max(minHeightPx, initialHeight - (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + + if (currentResizeDirection === 'bottom-left') { + newWidth = Math.max(minWidthPx, initialWidth - (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + newHeight = Math.max(minHeightPx, initialHeight + (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + + if (currentResizeDirection === 'bottom-right') { + newWidth = Math.max(minWidthPx, initialWidth + (e.clientX - initialX) * 2) + minWidth.value = `${newWidth}px` + newHeight = Math.max(minHeightPx, initialHeight + (e.clientY - initialY) * 2 - 20) + maxHeight.value = `${Math.min(newHeight, window.innerHeight - 165)}px` + } + } + // 停止调整大小的事件处理器 + const stopResizing = () => { + isResizing = false + document.removeEventListener('mousemove', handleResizing) + document.removeEventListener('mouseup', stopResizing) + } + + document.addEventListener('mousemove', handleResizing) + document.addEventListener('mouseup', stopResizing) + } + } + elDialog.addEventListener('mousemove', handleMouseMove) + elDialog.addEventListener('mousedown', handleMouseDown) + } + + return { + setupDrag, + maxHeight, + minWidth + } +} diff --git a/src/components/Dialog/index.ts b/src/components/Dialog/index.ts new file mode 100644 index 000000000..1655dadce --- /dev/null +++ b/src/components/Dialog/index.ts @@ -0,0 +1,3 @@ +import Dialog from './src/Dialog.vue' + +export { Dialog } diff --git a/src/components/Dialog/src/Dialog.vue b/src/components/Dialog/src/Dialog.vue new file mode 100644 index 000000000..611d702d1 --- /dev/null +++ b/src/components/Dialog/src/Dialog.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/components/Dialog/src/ResizeDialog.vue b/src/components/Dialog/src/ResizeDialog.vue new file mode 100644 index 000000000..d604e12a8 --- /dev/null +++ b/src/components/Dialog/src/ResizeDialog.vue @@ -0,0 +1,73 @@ + + diff --git a/src/components/Echart/index.ts b/src/components/Echart/index.ts new file mode 100644 index 000000000..482209210 --- /dev/null +++ b/src/components/Echart/index.ts @@ -0,0 +1,3 @@ +import Echart from './src/Echart.vue' + +export { Echart } diff --git a/src/components/Echart/src/Echart.vue b/src/components/Echart/src/Echart.vue new file mode 100644 index 000000000..58cae291f --- /dev/null +++ b/src/components/Echart/src/Echart.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/components/Editor/index.ts b/src/components/Editor/index.ts new file mode 100644 index 000000000..3fbf0a9c9 --- /dev/null +++ b/src/components/Editor/index.ts @@ -0,0 +1,8 @@ +import Editor from './src/Editor.vue' +import { IDomEditor } from '@wangeditor/editor' + +export interface EditorExpose { + getEditorRef: () => Promise +} + +export { Editor } diff --git a/src/components/Editor/src/Editor.vue b/src/components/Editor/src/Editor.vue new file mode 100644 index 000000000..0bb3452c0 --- /dev/null +++ b/src/components/Editor/src/Editor.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/src/components/Error/index.ts b/src/components/Error/index.ts new file mode 100644 index 000000000..a52c6f97d --- /dev/null +++ b/src/components/Error/index.ts @@ -0,0 +1,3 @@ +import Error from './src/Error.vue' + +export { Error } diff --git a/src/components/Error/src/Error.vue b/src/components/Error/src/Error.vue new file mode 100644 index 000000000..b18af6009 --- /dev/null +++ b/src/components/Error/src/Error.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/components/Footer/index.ts b/src/components/Footer/index.ts new file mode 100644 index 000000000..bd052e0c4 --- /dev/null +++ b/src/components/Footer/index.ts @@ -0,0 +1,3 @@ +import Footer from './src/Footer.vue' + +export { Footer } diff --git a/src/components/Footer/src/Footer.vue b/src/components/Footer/src/Footer.vue new file mode 100644 index 000000000..50b7ce755 --- /dev/null +++ b/src/components/Footer/src/Footer.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/Form/index.ts b/src/components/Form/index.ts new file mode 100644 index 000000000..6688425d5 --- /dev/null +++ b/src/components/Form/index.ts @@ -0,0 +1,48 @@ +import Form from './src/Form.vue' +import type { FormSchema, FormSetProps } from './src/types' +export type { + ComponentNameEnum, + ComponentName, + InputComponentProps, + AutocompleteComponentProps, + InputNumberComponentProps, + SelectOption, + SelectComponentProps, + SelectV2ComponentProps, + CascaderComponentProps, + SwitchComponentProps, + RateComponentProps, + ColorPickerComponentProps, + TransferComponentProps, + RadioOption, + RadioGroupComponentProps, + RadioButtonComponentProps, + CheckboxOption, + CheckboxGroupComponentProps, + DividerComponentProps, + DatePickerComponentProps, + DateTimePickerComponentProps, + TimePickerComponentProps, + TimeSelectComponentProps, + ColProps, + FormSetProps, + FormItemProps, + FormSchema, + FormProps, + PlaceholderModel, + InputPasswordComponentProps, + TreeSelectComponentProps +} from './src/types' + +export interface FormExpose { + setValues: (data: Recordable) => void + setProps: (props: Recordable) => void + delSchema: (field: string) => void + addSchema: (formSchema: FormSchema, index?: number) => void + setSchema: (schemaProps: FormSetProps[]) => void + formModel: Recordable + getComponentExpose: (field: string) => any + getFormItemExpose: (field: string) => any +} + +export { Form } diff --git a/src/components/Form/src/Form.vue b/src/components/Form/src/Form.vue new file mode 100644 index 000000000..eb18f759e --- /dev/null +++ b/src/components/Form/src/Form.vue @@ -0,0 +1,442 @@ + + + diff --git a/src/components/Form/src/components/useRenderCheckbox.tsx b/src/components/Form/src/components/useRenderCheckbox.tsx new file mode 100644 index 000000000..63afb100f --- /dev/null +++ b/src/components/Form/src/components/useRenderCheckbox.tsx @@ -0,0 +1,31 @@ +import { FormSchema, ComponentNameEnum, CheckboxGroupComponentProps } from '../types' +import { ElCheckbox, ElCheckboxButton } from 'element-plus' +import { defineComponent } from 'vue' + +export const useRenderCheckbox = () => { + const renderCheckboxOptions = (item: FormSchema) => { + // 如果有别名,就取别名 + const componentProps = item?.componentProps as CheckboxGroupComponentProps + const valueAlias = componentProps?.props?.value || 'value' + const labelAlias = componentProps?.props?.label || 'label' + const disabledAlias = componentProps?.props?.disabled || 'disabled' + const Com = ( + item.component === ComponentNameEnum.CHECKBOX_GROUP ? ElCheckbox : ElCheckboxButton + ) as ReturnType + return componentProps?.options?.map((option) => { + const { ...other } = option + return ( + + ) + }) + } + + return { + renderCheckboxOptions + } +} diff --git a/src/components/Form/src/components/useRenderRadio.tsx b/src/components/Form/src/components/useRenderRadio.tsx new file mode 100644 index 000000000..fc9842bde --- /dev/null +++ b/src/components/Form/src/components/useRenderRadio.tsx @@ -0,0 +1,31 @@ +import { FormSchema, ComponentNameEnum, RadioGroupComponentProps } from '../types' +import { ElRadio, ElRadioButton } from 'element-plus' +import { defineComponent } from 'vue' + +export const useRenderRadio = () => { + const renderRadioOptions = (item: FormSchema) => { + // 如果有别名,就取别名 + const componentProps = item?.componentProps as RadioGroupComponentProps + const valueAlias = componentProps?.props?.value || 'value' + const labelAlias = componentProps?.props?.label || 'label' + const disabledAlias = componentProps?.props?.disabled || 'disabled' + const Com = ( + item.component === ComponentNameEnum.RADIO_GROUP ? ElRadio : ElRadioButton + ) as ReturnType + return componentProps?.options?.map((option) => { + const { ...other } = option + return ( + + ) + }) + } + + return { + renderRadioOptions + } +} diff --git a/src/components/Form/src/components/useRenderSelect.tsx b/src/components/Form/src/components/useRenderSelect.tsx new file mode 100644 index 000000000..46389af29 --- /dev/null +++ b/src/components/Form/src/components/useRenderSelect.tsx @@ -0,0 +1,58 @@ +import { ElOption, ElOptionGroup } from 'element-plus' +import { FormSchema, SelectComponentProps, SelectOption } from '../types' + +export const useRenderSelect = () => { + // 渲染 select options + const renderSelectOptions = (item: FormSchema) => { + const componentsProps = item?.componentProps as SelectComponentProps + const optionGroupDefaultSlot = componentsProps?.slots?.optionGroupDefault + // 如果有别名,就取别名 + const labelAlias = componentsProps?.props?.label + const keyAlias = componentsProps?.props?.key + return componentsProps?.options?.map((option) => { + if (option?.options?.length) { + return optionGroupDefaultSlot ? ( + optionGroupDefaultSlot(option) + ) : ( + + {{ + default: () => + option?.options?.map((v) => { + return renderSelectOptionItem(item, v) + }) + }} + + ) + } else { + return renderSelectOptionItem(item, option) + } + }) + } + + // 渲染 select option item + const renderSelectOptionItem = (item: FormSchema, option: SelectOption) => { + // 如果有别名,就取别名 + const componentsProps = item.componentProps as SelectComponentProps + const labelAlias = componentsProps?.props?.label + const valueAlias = componentsProps?.props?.value + const keyAlias = componentsProps?.props?.key + const optionDefaultSlot = componentsProps.slots?.optionDefault + + return ( + + {{ + default: () => (optionDefaultSlot ? optionDefaultSlot(option) : undefined) + }} + + ) + } + + return { + renderSelectOptions + } +} diff --git a/src/components/Form/src/helper/componentMap.ts b/src/components/Form/src/helper/componentMap.ts new file mode 100644 index 000000000..df2714f77 --- /dev/null +++ b/src/components/Form/src/helper/componentMap.ts @@ -0,0 +1,59 @@ +import type { Component } from 'vue' +import { + ElCascader, + ElCheckboxGroup, + ElColorPicker, + ElDatePicker, + ElInput, + ElInputNumber, + ElRadioGroup, + ElRate, + ElSelect, + ElSelectV2, + ElSlider, + ElSwitch, + ElTimePicker, + ElTimeSelect, + ElTransfer, + ElAutocomplete, + ElDivider, + ElTreeSelect, + ElUpload +} from 'element-plus' +import { InputPassword } from '@/components/InputPassword' +import { Editor } from '@/components/Editor' +import { JsonEditor } from '@/components/JsonEditor' +import { IconPicker } from '@/components/IconPicker' +import { IAgree } from '@/components/IAgree' +import { ComponentName } from '../types' + +const componentMap: Recordable = { + RadioGroup: ElRadioGroup, + RadioButton: ElRadioGroup, + CheckboxGroup: ElCheckboxGroup, + CheckboxButton: ElCheckboxGroup, + Input: ElInput, + Autocomplete: ElAutocomplete, + InputNumber: ElInputNumber, + Select: ElSelect, + Cascader: ElCascader, + Switch: ElSwitch, + Slider: ElSlider, + TimePicker: ElTimePicker, + DatePicker: ElDatePicker, + Rate: ElRate, + ColorPicker: ElColorPicker, + Transfer: ElTransfer, + Divider: ElDivider, + TimeSelect: ElTimeSelect, + SelectV2: ElSelectV2, + InputPassword: InputPassword, + Editor: Editor, + TreeSelect: ElTreeSelect, + Upload: ElUpload, + JsonEditor: JsonEditor, + IconPicker: IconPicker, + IAgree: IAgree +} + +export { componentMap } diff --git a/src/components/Form/src/helper/index.ts b/src/components/Form/src/helper/index.ts new file mode 100644 index 000000000..3ddb1b43a --- /dev/null +++ b/src/components/Form/src/helper/index.ts @@ -0,0 +1,169 @@ +import { useI18n } from '@/hooks/web/useI18n' +import { PlaceholderModel, FormSchema, ComponentNameEnum, ColProps } from '../types' +import { isFunction } from '@/utils/is' +import { firstUpperCase, humpToDash } from '@/utils' +import { set, get } from 'lodash-es' + +const { t } = useI18n() + +/** + * + * @param schema 对应组件数据 + * @returns 返回提示信息对象 + * @description 用于自动设置placeholder + */ +export const setTextPlaceholder = (schema: FormSchema): PlaceholderModel => { + const textMap = [ + ComponentNameEnum.INPUT, + ComponentNameEnum.AUTOCOMPLETE, + ComponentNameEnum.INPUT_NUMBER, + ComponentNameEnum.INPUT_PASSWORD + ] + const selectMap = [ + ComponentNameEnum.SELECT, + ComponentNameEnum.TIME_PICKER, + ComponentNameEnum.DATE_PICKER, + ComponentNameEnum.TIME_SELECT, + ComponentNameEnum.SELECT_V2 + ] + if (textMap.includes(schema?.component as ComponentNameEnum)) { + return { + placeholder: t('common.inputText') + } + } + if (selectMap.includes(schema?.component as ComponentNameEnum)) { + // 一些范围选择器 + const twoTextMap = ['datetimerange', 'daterange', 'monthrange', 'datetimerange', 'daterange'] + if ( + twoTextMap.includes( + ((schema?.componentProps as any)?.type || + (schema?.componentProps as any)?.isRange) as string + ) + ) { + return { + startPlaceholder: t('common.startTimeText'), + endPlaceholder: t('common.endTimeText'), + rangeSeparator: '-' + } + } else { + return { + placeholder: t('common.selectText') + } + } + } + return {} +} + +/** + * + * @param col 内置栅格 + * @returns 返回栅格属性 + * @description 合并传入进来的栅格属性 + */ +export const setGridProp = (col: ColProps = {}): ColProps => { + const colProps: ColProps = { + // 如果有span,代表用户优先级更高,所以不需要默认栅格 + ...(col.span + ? {} + : { + xs: 24, + sm: 12, + md: 12, + lg: 12, + xl: 12 + }), + ...col + } + return colProps +} + +/** + * + * @param item 传入的组件属性 + * @returns 默认添加 clearable 属性 + */ +export const setComponentProps = (item: FormSchema): Recordable => { + // const notNeedClearable = ['ColorPicker'] + // 拆分事件并组合 + const onEvents = (item?.componentProps as any)?.on || {} + const newOnEvents: Recordable = {} + + for (const key in onEvents) { + if (onEvents[key]) { + newOnEvents[`on${firstUpperCase(key)}`] = (...args: any[]) => { + onEvents[key](...args) + } + } + } + + const componentProps: Recordable = { + clearable: true, + ...item.componentProps, + ...newOnEvents + } + // 需要删除额外的属性 + if (componentProps.slots) { + delete componentProps.slots + } + if (componentProps.on) { + delete componentProps.on + } + return componentProps +} + +/** + * + * @param formModel 表单数据 + * @param slotsProps 插槽属性 + */ +export const setItemComponentSlots = (slotsProps: Recordable = {}): Recordable => { + const slotObj: Recordable = {} + for (const key in slotsProps) { + if (slotsProps[key]) { + if (isFunction(slotsProps[key])) { + slotObj[humpToDash(key)] = (...args: any[]) => { + return slotsProps[key]?.(...args) + } + } else { + slotObj[humpToDash(key)] = () => { + return slotsProps[key] + } + } + } + } + return slotObj +} + +/** + * + * @param schema Form表单结构化数组 + * @param formModel FormMoel + * @returns FormMoel + * @description 生成对应的formModel + */ +export const initModel = (schema: FormSchema[], formModel: Recordable) => { + const model: Recordable = { ...formModel } + schema.map((v) => { + if (v.remove) { + delete model[v.field] + } else if (v.component !== 'Divider') { + // const hasField = Reflect.has(model, v.field) + const hasField = get(model, v.field) + // 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值 + set( + model, + v.field, + hasField !== void 0 ? get(model, v.field) : v.value !== void 0 ? v.value : undefined + ) + // model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : undefined + } + }) + // 如果 schema 对应的 field 不存在,则删除 model 中的对应的 field + for (let i = 0; i < schema.length; i++) { + const key = schema[i].field + if (!get(model, key) && get(model, key) !== 0) { + delete model[key] + } + } + return model +} diff --git a/src/components/Form/src/types/index.ts b/src/components/Form/src/types/index.ts new file mode 100644 index 000000000..4cb213f07 --- /dev/null +++ b/src/components/Form/src/types/index.ts @@ -0,0 +1,675 @@ +import { + AutocompleteProps, + InputNumberProps, + CascaderProps, + CascaderNode, + CascaderValue, + SwitchProps, + ComponentSize, + InputProps, + RateProps, + ColorPickerProps, + TransferProps, + RadioGroupProps, + RadioButtonProps, + CheckboxGroupProps, + DividerProps, + DatePickerProps, + FormItemProps as ElFormItemProps, + FormProps as ElFormProps, + ISelectProps, + UploadProps +} from 'element-plus' +import { IEditorConfig } from '@wangeditor/editor' +import { JsonEditorProps } from '@/components/JsonEditor' +import { IAgreeProps } from '@/components/IAgree' +import { CSSProperties } from 'vue' + +export interface PlaceholderModel { + placeholder?: string + startPlaceholder?: string + endPlaceholder?: string + rangeSeparator?: string +} + +export enum ComponentNameEnum { + RADIO_GROUP = 'RadioGroup', + RADIO_BUTTON = 'RadioButton', + CHECKBOX_GROUP = 'CheckboxGroup', + CHECKBOX_BUTTON = 'CheckboxButton', + INPUT = 'Input', + AUTOCOMPLETE = 'Autocomplete', + INPUT_NUMBER = 'InputNumber', + SELECT = 'Select', + CASCADER = 'Cascader', + SWITCH = 'Switch', + SLIDER = 'Slider', + TIME_PICKER = 'TimePicker', + DATE_PICKER = 'DatePicker', + RATE = 'Rate', + COLOR_PICKER = 'ColorPicker', + TRANSFER = 'Transfer', + DIVIDER = 'Divider', + TIME_SELECT = 'TimeSelect', + SELECT_V2 = 'SelectV2', + INPUT_PASSWORD = 'InputPassword', + EDITOR = 'Editor', + TREE_SELECT = 'TreeSelect', + UPLOAD = 'Upload', + JSON_EDITOR = 'JsonEditor', + ICON_PICKER = 'IconPicker', + I_AGREE = 'IAgree' +} + +type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K + ? K extends string + ? K extends `${infer A}_${infer B}` + ? `${Capitalize>}${Capitalize>}` + : Capitalize> + : never + : never + +export type ComponentName = CamelCaseComponentName + +export interface InputPasswordComponentProps { + strength?: boolean + style?: CSSProperties +} + +export interface InputComponentProps extends Partial { + rows?: number + on?: { + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + change?: (value: string | number) => void + clear?: () => void + input?: (value: string | number) => void + } + slots?: { + prefix?: (...args: any[]) => JSX.Element | null + suffix?: (...args: any[]) => JSX.Element | null + prepend?: (...args: any[]) => JSX.Element | null + append?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface AutocompleteComponentProps extends Partial { + on?: { + select?: (item: any) => void + change?: (value: string | number) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + prefix?: (...args: any[]) => JSX.Element | null + suffix?: (...args: any[]) => JSX.Element | null + prepend?: (...args: any[]) => JSX.Element | null + append?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface InputNumberComponentProps extends Partial { + on?: { + change?: (currentValue: number | undefined, oldValue: number | undefined) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } + style?: CSSProperties +} + +export interface SelectOption { + label?: string + disabled?: boolean + value?: any + key?: string | number + options?: SelectOption[] + [key: string]: any +} + +export interface SelectComponentProps extends Omit, 'options'> { + /** + * 数据源的字段别名 + */ + props?: { + key?: string + value?: string + label?: string + children?: string + } + on?: { + change?: (value: string | number | boolean | Object) => void + visibleChange?: (visible: boolean) => void + removeTag?: (tag: any) => void + clear?: () => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } + slots?: { + default?: (options: SelectOption[]) => JSX.Element[] | null + optionGroupDefault?: (item: SelectOption) => JSX.Element + optionDefault?: (option: SelectOption) => JSX.Element | null + prefix?: (...args: any[]) => JSX.Element | null + empty?: (...args: any[]) => JSX.Element | null + } + options?: SelectOption[] + style?: CSSProperties +} + +export interface SelectV2ComponentProps { + multiple?: boolean + disabled?: boolean + valueKey?: string + size?: ComponentSize + clearable?: boolean + clearIcon?: string | JSX.Element | null + collapseTags?: boolean + multipleLimit?: number + name?: string + effect?: string + autocomplete?: string + placeholder?: string + filterable?: boolean + allowCreate?: boolean + reserveKeyword?: boolean + noDataText?: string + popperClass?: string + teleported?: boolean + persistent?: boolean + popperOptions?: any + automaticDropdown?: boolean + height?: number + scrollbarAlwaysOn?: boolean + remote?: boolean + remoteMethod?: (query: string) => void + validateEvent?: boolean + placement?: AutocompleteProps['placement'] + collapseTagsTooltip?: boolean + on?: { + change?: (value: string | number | boolean | Object) => void + visibleChange?: (visible: boolean) => void + removeTag?: (tag: any) => void + clear?: () => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } + options?: SelectOption[] + slots?: { + default?: (option: SelectOption) => JSX.Element | null + } + style?: CSSProperties +} + +export interface CascaderComponentProps { + options?: Record[] + props?: CascaderProps + size?: ComponentSize + placeholder?: string + disabled?: boolean + clearable?: boolean + showAllLevels?: boolean + collapseTags?: boolean + collapseTagsTooltip?: boolean + separator?: string + filterable?: boolean + filterMethod?: (node: CascaderNode, keyword: string) => boolean + debounce?: number + beforeFilter?: (value: string) => boolean + popperClass?: string + teleported?: boolean + tagType?: ElementPlusInfoType + validateEvent?: boolean + on?: { + change?: (value: CascaderValue) => void + expandChange?: (value: CascaderValue) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + visibleChange?: (value: boolean) => void + removeTag?: (value: CascaderNode['valueByOption']) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + empty?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface SwitchComponentProps extends Partial { + on?: { + change?: (value: boolean | string | number) => void + } + style?: CSSProperties +} + +export interface RateComponentProps extends Partial { + on?: { + change?: (value: number) => void + } + style?: CSSProperties +} + +export interface ColorPickerComponentProps extends Partial { + on?: { + change?: (value: string) => void + activeChange?: (value: string) => void + } + style?: CSSProperties +} + +export interface TransferComponentProps extends Partial { + on?: { + change?: ( + value: number | string, + direction: 'left' | 'right', + movedKeys: string[] | number[] + ) => void + leftCheckChange?: (value: any[]) => void + rightCheckChange?: (value: any[]) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + leftFooter?: (...args: any[]) => JSX.Element | null + rightFooter?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface RadioOption { + label?: string + value?: string | number | boolean + disabled?: boolean + border?: boolean + size?: ComponentSize + name?: string + [key: string]: any +} +export interface RadioGroupComponentProps extends Partial { + options?: RadioOption[] + /** + * 数据源的字段别名 + */ + props?: { + label?: string + value?: string + disabled?: string + } + on?: { + change?: (value: string | number | boolean) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element[] | null + } + style?: CSSProperties +} + +export interface RadioButtonComponentProps extends Partial { + options?: RadioOption[] + /** + * 数据源的字段别名 + */ + props?: { + label?: string + value?: string + disabled?: string + } + on?: { + change?: (value: string | number | boolean) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element[] | null + } + style?: CSSProperties +} + +export interface CheckboxOption { + label?: string + value?: string | number | boolean + disabled?: boolean + trueLabel?: string | number + falseLabel?: string | number + border?: boolean + size?: ComponentSize + name?: string + checked?: boolean + indeterminate?: boolean + validateEvent?: boolean + tabindex?: number | string + id?: string + controls?: boolean + [key: string]: any +} + +export interface CheckboxGroupComponentProps extends Partial { + options?: CheckboxOption[] + /** + * 数据源的字段别名 + */ + props?: { + label?: string + value?: string + disabled?: string + } + on?: { + change?: (value: string | number | boolean) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element[] | null + } + style?: CSSProperties +} + +export interface DividerComponentProps extends Partial { + on?: { + change?: (value: number) => void + input?: (value: number) => void + } + style?: CSSProperties +} + +export interface DatePickerComponentProps extends Partial { + on?: { + change?: (value: string | Date | number | string[]) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + calendarChange?: (val: [Date, Date]) => void + panelChange?: (date, mode, view) => void + visibleChange?: (visibility: boolean) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + rangeSeparator?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface DateTimePickerComponentProps { + readonly?: boolean + disabled?: boolean + editable?: boolean + clearable?: boolean + size?: ComponentSize + placeholder?: string + startPlaceholder?: string + endPlaceholder?: string + timeArrowControl?: boolean + type?: 'year' | 'month' | 'date' | 'datetime' | 'datetimerange' | 'daterange' | 'week' + format?: string + popperClass?: string + rangeSeparator?: string + defaultValue?: Date | [Date, Date] + defaultTime?: Date | [Date, Date] + valueFormat?: string + id?: string + name?: string + unlinkPanels?: boolean + prefixIcon?: string | JSX.Element + clearIcon?: string | JSX.Element + shortcuts?: Array<{ text: string; value: Date | Function }> + disabledDate?: (date: Date) => boolean + cellClassName?: string | ((date: Date) => string | undefined) + teleported?: boolean + on?: { + change?: (value: string | Date | number | string[]) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + calendarChange?: (val: [Date, Date]) => void + visibleChange?: (visibility: boolean) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + rangeSeparator?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface TimePickerComponentProps { + readonly?: boolean + disabled?: boolean + editable?: boolean + clearable?: boolean + size?: ComponentSize + placeholder?: string + startPlaceholder?: string + endPlaceholder?: string + isRange?: boolean + arrowControl?: boolean + popperClass?: string + rangeSeparator?: string + format?: string + defaultValue?: Date | [Date, Date] + id?: string + name?: string + label?: string + prefixIcon?: string | JSX.Element + clearIcon?: string | JSX.Element + disabledHours?: (role: string, comparingDate?: any) => number[] + disabledMinutes?: (hour: number, role: string, comparingDate?: any) => number[] + disabledSeconds?: (hour: number, minute: number, role: string, comparingDate?: any) => number[] + teleported?: boolean + tabindex?: number | string + on?: { + change: ( + val: number | string | Date | [number, number] | [string, string] | [Date, Date] + ) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + visibleChange?: (visibility: boolean) => void + } + style?: CSSProperties +} + +export interface TimeSelectComponentProps { + disabled?: boolean + editable?: boolean + clearable?: boolean + size?: ComponentSize + placeholder?: string + name?: string + effect?: string + prefixIcon?: string | JSX.Element + clearIcon?: string | JSX.Element + start?: string + end?: string + step?: string + minTime?: string + maxTime?: string + format?: string + on?: { + change?: (val: string) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } + style?: CSSProperties +} + +export interface EditorComponentProps { + editorConfig?: IEditorConfig + style?: CSSProperties +} + +export interface ColProps { + span?: number + xs?: number + sm?: number + md?: number + lg?: number + xl?: number + tag?: string +} + +export interface FormSetProps { + field: string + path: string + value: any +} + +export interface FormItemProps extends Partial { + style?: CSSProperties + slots?: { + default?: (...args: any[]) => JSX.Element | null + label?: (...args: any[]) => JSX.Element | null + error?: (...args: any[]) => JSX.Element | null + } +} + +export interface UploadComponentProps extends Partial { + slots?: { + default?: (...args: any[]) => JSX.Element | null + trigger?: (...args: any[]) => JSX.Element | null + tip?: (...args: any[]) => JSX.Element | null + file?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface TreeSelectComponentProps + extends Omit, 'props' | 'on' | 'slots'> { + data?: any[] + emptyText?: string + nodeKey?: string + props?: { + children?: string + label?: string | ((...args: any[]) => string) + disabled?: string | ((...args: any[]) => string) + isLeaf?: string | ((...args: any[]) => string) + class?: string | ((...args: any[]) => string) + } + renderAfterExpand?: boolean + load?: (...args: any[]) => Promise + renderContent?: (...args: any[]) => JSX.Element | null + highlightCurrent?: boolean + defaultExpandAll?: boolean + expandOnClickNode?: boolean + checkOnClickNode?: boolean + autoExpandParent?: boolean + defaultExpandedKeys?: any[] + showCheckbox?: boolean + checkStrictly?: boolean + defaultCheckedKeys?: any[] + currentNodeKey?: string | number + filterNodeMethod?: (...args: any[]) => boolean + accordion?: boolean + indent?: number + icon?: string | ((...args: any[]) => JSX.Element | null) + lazy?: boolean + draggable?: boolean + allowDrag?: (...args: any[]) => boolean + allowDrop?: (...args: any[]) => boolean + on?: { + change?: (value: string | number | boolean | Object) => void + visibleChange?: (visible: boolean) => void + removeTag?: (tag: any) => void + clear?: () => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + nodeClick?: (...args: any[]) => void + nodeContextMenu?: (...args: any[]) => void + checkChange?: (...args: any[]) => void + check?: (...args: any[]) => void + currentChange?: (...args: any[]) => void + nodeExpand?: (...args: any[]) => void + nodeCollapse?: (...args: any[]) => void + nodeDragStart?: (...args: any[]) => void + nodeDragEnter?: (...args: any[]) => void + nodeDragLeave?: (...args: any[]) => void + nodeDragOver?: (...args: any[]) => void + nodeDragEnd?: (...args: any[]) => void + nodeDrop?: (...args: any[]) => void + } + slots?: { + default?: (...args: any[]) => JSX.Element | null + optionGroupDefault?: (item: SelectOption) => JSX.Element + optionDefault?: (option: SelectOption) => JSX.Element | null + prefix?: (...args: any[]) => JSX.Element | null + empty?: (...args: any[]) => JSX.Element | null + } + style?: CSSProperties +} + +export interface FormSchema { + /** + * 唯一标识 + */ + field: string + + /** + * 标题 + */ + label?: string + + /** + * col组件属性 + */ + colProps?: ColProps + + /** + * 表单组件属性,具体可以查看element-plus文档 + */ + componentProps?: + | InputComponentProps + | AutocompleteComponentProps + | InputNumberComponentProps + | SelectComponentProps + | SelectV2ComponentProps + | CascaderComponentProps + | SwitchComponentProps + | RateComponentProps + | ColorPickerComponentProps + | TransferComponentProps + | RadioGroupComponentProps + | RadioButtonComponentProps + | DividerComponentProps + | DatePickerComponentProps + | DateTimePickerComponentProps + | TimePickerComponentProps + | InputPasswordComponentProps + | TreeSelectComponentProps + | UploadComponentProps + | JsonEditorProps + | IAgreeProps + | any + + /** + * formItem组件属性,具体可以查看element-plus文档 + */ + formItemProps?: FormItemProps + + /** + * 渲染的组件名称 + */ + component?: ComponentName + + /** + * 初始值 + */ + value?: any + + /** + * 是否隐藏,如果为true,会连同值一同删除,类似v-if + */ + remove?: boolean + + /** + * 样式隐藏,不会把值一同删掉,类似v-show + */ + hidden?: boolean + + /** + * 是否显示,动态控制表单项显示隐藏 + */ + ifShow?: boolean + + /** + * @returns 远程加载下拉项 + */ + optionApi?: any +} + +export interface FormProps extends Partial { + schema?: FormSchema[] + isCol?: boolean + model?: Recordable + autoSetPlaceholder?: boolean + isCustom?: boolean + [key: string]: any +} diff --git a/src/components/Highlight/index.ts b/src/components/Highlight/index.ts new file mode 100644 index 000000000..3e2d9ed60 --- /dev/null +++ b/src/components/Highlight/index.ts @@ -0,0 +1,3 @@ +import Highlight from './src/Highlight.vue' + +export { Highlight } diff --git a/src/components/Highlight/src/Highlight.vue b/src/components/Highlight/src/Highlight.vue new file mode 100644 index 000000000..ef923a9a4 --- /dev/null +++ b/src/components/Highlight/src/Highlight.vue @@ -0,0 +1,65 @@ + diff --git a/src/components/IAgree/index.ts b/src/components/IAgree/index.ts new file mode 100644 index 000000000..8c3112580 --- /dev/null +++ b/src/components/IAgree/index.ts @@ -0,0 +1,4 @@ +import IAgree from './src/IAgree.vue' + +export type { LinkItem, IAgreeProps } from './src/types' +export { IAgree } diff --git a/src/components/IAgree/src/IAgree.vue b/src/components/IAgree/src/IAgree.vue new file mode 100644 index 000000000..6a36e23a9 --- /dev/null +++ b/src/components/IAgree/src/IAgree.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/components/IAgree/src/types/index.ts b/src/components/IAgree/src/types/index.ts new file mode 100644 index 000000000..9ddef757e --- /dev/null +++ b/src/components/IAgree/src/types/index.ts @@ -0,0 +1,10 @@ +export interface LinkItem { + text: string + url?: string + onClick?: () => void +} + +export interface IAgreeProps { + text: string + link: LinkItem[] +} diff --git a/src/components/Icon/index.ts b/src/components/Icon/index.ts new file mode 100644 index 000000000..83469d4b4 --- /dev/null +++ b/src/components/Icon/index.ts @@ -0,0 +1,5 @@ +import Icon from './src/Icon.vue' + +export type { IconTypes } from './src/types' + +export { Icon } diff --git a/src/components/Icon/src/Icon.vue b/src/components/Icon/src/Icon.vue new file mode 100644 index 000000000..0fa4d7362 --- /dev/null +++ b/src/components/Icon/src/Icon.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/components/Icon/src/types/index.ts b/src/components/Icon/src/types/index.ts new file mode 100644 index 000000000..632e4e892 --- /dev/null +++ b/src/components/Icon/src/types/index.ts @@ -0,0 +1,6 @@ +export interface IconTypes { + size?: number + color?: string + icon: string + hoverColor?: string +} diff --git a/src/components/IconPicker/index.ts b/src/components/IconPicker/index.ts new file mode 100644 index 000000000..b7b302217 --- /dev/null +++ b/src/components/IconPicker/index.ts @@ -0,0 +1,3 @@ +import IconPicker from './src/IconPicker.vue' + +export { IconPicker } diff --git a/src/components/IconPicker/src/IconPicker.vue b/src/components/IconPicker/src/IconPicker.vue new file mode 100644 index 000000000..34f350d3d --- /dev/null +++ b/src/components/IconPicker/src/IconPicker.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/components/IconPicker/src/data/icons.ant-design.ts b/src/components/IconPicker/src/data/icons.ant-design.ts new file mode 100644 index 000000000..eab2169a9 --- /dev/null +++ b/src/components/IconPicker/src/data/icons.ant-design.ts @@ -0,0 +1,836 @@ +export default { + name: 'Ant Design Icons', + prefix: 'vi-ant-design', + icons: [ + 'vi-ant-design:account-book-filled', + 'vi-ant-design:account-book-outlined', + 'vi-ant-design:account-book-twotone', + 'vi-ant-design:aim-outlined', + 'vi-ant-design:alert-filled', + 'vi-ant-design:alert-outlined', + 'vi-ant-design:alert-twotone', + 'vi-ant-design:alibaba-outlined', + 'vi-ant-design:align-center-outlined', + 'vi-ant-design:align-left-outlined', + 'vi-ant-design:align-right-outlined', + 'vi-ant-design:alipay-circle-filled', + 'vi-ant-design:alipay-circle-outlined', + 'vi-ant-design:alipay-outlined', + 'vi-ant-design:alipay-square-filled', + 'vi-ant-design:aliwangwang-filled', + 'vi-ant-design:aliwangwang-outlined', + 'vi-ant-design:aliyun-outlined', + 'vi-ant-design:amazon-circle-filled', + 'vi-ant-design:amazon-outlined', + 'vi-ant-design:amazon-square-filled', + 'vi-ant-design:android-filled', + 'vi-ant-design:android-outlined', + 'vi-ant-design:ant-cloud-outlined', + 'vi-ant-design:ant-design-outlined', + 'vi-ant-design:apartment-outlined', + 'vi-ant-design:api-filled', + 'vi-ant-design:api-outlined', + 'vi-ant-design:api-twotone', + 'vi-ant-design:apple-filled', + 'vi-ant-design:apple-outlined', + 'vi-ant-design:appstore-add-outlined', + 'vi-ant-design:appstore-filled', + 'vi-ant-design:appstore-outlined', + 'vi-ant-design:appstore-twotone', + 'vi-ant-design:area-chart-outlined', + 'vi-ant-design:arrow-down-outlined', + 'vi-ant-design:arrow-left-outlined', + 'vi-ant-design:arrow-right-outlined', + 'vi-ant-design:arrow-up-outlined', + 'vi-ant-design:arrows-alt-outlined', + 'vi-ant-design:audio-filled', + 'vi-ant-design:audio-muted-outlined', + 'vi-ant-design:audio-outlined', + 'vi-ant-design:audio-twotone', + 'vi-ant-design:audit-outlined', + 'vi-ant-design:backward-filled', + 'vi-ant-design:backward-outlined', + 'vi-ant-design:baidu-outlined', + 'vi-ant-design:bank-filled', + 'vi-ant-design:bank-outlined', + 'vi-ant-design:bank-twotone', + 'vi-ant-design:bar-chart-outlined', + 'vi-ant-design:barcode-outlined', + 'vi-ant-design:bars-outlined', + 'vi-ant-design:behance-circle-filled', + 'vi-ant-design:behance-outlined', + 'vi-ant-design:behance-square-filled', + 'vi-ant-design:behance-square-outlined', + 'vi-ant-design:bell-filled', + 'vi-ant-design:bell-outlined', + 'vi-ant-design:bell-twotone', + 'vi-ant-design:bg-colors-outlined', + 'vi-ant-design:bilibili-filled', + 'vi-ant-design:bilibili-outlined', + 'vi-ant-design:block-outlined', + 'vi-ant-design:bold-outlined', + 'vi-ant-design:book-filled', + 'vi-ant-design:book-outlined', + 'vi-ant-design:book-twotone', + 'vi-ant-design:border-bottom-outlined', + 'vi-ant-design:border-horizontal-outlined', + 'vi-ant-design:border-inner-outlined', + 'vi-ant-design:border-left-outlined', + 'vi-ant-design:border-outer-outlined', + 'vi-ant-design:border-outlined', + 'vi-ant-design:border-right-outlined', + 'vi-ant-design:border-top-outlined', + 'vi-ant-design:border-verticle-outlined', + 'vi-ant-design:borderless-table-outlined', + 'vi-ant-design:box-plot-filled', + 'vi-ant-design:box-plot-outlined', + 'vi-ant-design:box-plot-twotone', + 'vi-ant-design:branches-outlined', + 'vi-ant-design:bug-filled', + 'vi-ant-design:bug-outlined', + 'vi-ant-design:bug-twotone', + 'vi-ant-design:build-filled', + 'vi-ant-design:build-outlined', + 'vi-ant-design:build-twotone', + 'vi-ant-design:bulb-filled', + 'vi-ant-design:bulb-outlined', + 'vi-ant-design:bulb-twotone', + 'vi-ant-design:calculator-filled', + 'vi-ant-design:calculator-outlined', + 'vi-ant-design:calculator-twotone', + 'vi-ant-design:calendar-filled', + 'vi-ant-design:calendar-outlined', + 'vi-ant-design:calendar-twotone', + 'vi-ant-design:camera-filled', + 'vi-ant-design:camera-outlined', + 'vi-ant-design:camera-twotone', + 'vi-ant-design:car-filled', + 'vi-ant-design:car-outlined', + 'vi-ant-design:car-twotone', + 'vi-ant-design:caret-down-filled', + 'vi-ant-design:caret-down-outlined', + 'vi-ant-design:caret-left-filled', + 'vi-ant-design:caret-left-outlined', + 'vi-ant-design:caret-right-filled', + 'vi-ant-design:caret-right-outlined', + 'vi-ant-design:caret-up-filled', + 'vi-ant-design:caret-up-outlined', + 'vi-ant-design:carry-out-filled', + 'vi-ant-design:carry-out-outlined', + 'vi-ant-design:carry-out-twotone', + 'vi-ant-design:check-circle-filled', + 'vi-ant-design:check-circle-outlined', + 'vi-ant-design:check-circle-twotone', + 'vi-ant-design:check-outlined', + 'vi-ant-design:check-square-filled', + 'vi-ant-design:check-square-outlined', + 'vi-ant-design:check-square-twotone', + 'vi-ant-design:chrome-filled', + 'vi-ant-design:chrome-outlined', + 'vi-ant-design:ci-circle-filled', + 'vi-ant-design:ci-circle-outlined', + 'vi-ant-design:ci-circle-twotone', + 'vi-ant-design:ci-outlined', + 'vi-ant-design:ci-twotone', + 'vi-ant-design:clear-outlined', + 'vi-ant-design:clock-circle-filled', + 'vi-ant-design:clock-circle-outlined', + 'vi-ant-design:clock-circle-twotone', + 'vi-ant-design:close-circle-filled', + 'vi-ant-design:close-circle-outlined', + 'vi-ant-design:close-circle-twotone', + 'vi-ant-design:close-outlined', + 'vi-ant-design:close-square-filled', + 'vi-ant-design:close-square-outlined', + 'vi-ant-design:close-square-twotone', + 'vi-ant-design:cloud-download-outlined', + 'vi-ant-design:cloud-filled', + 'vi-ant-design:cloud-outlined', + 'vi-ant-design:cloud-server-outlined', + 'vi-ant-design:cloud-sync-outlined', + 'vi-ant-design:cloud-twotone', + 'vi-ant-design:cloud-upload-outlined', + 'vi-ant-design:cluster-outlined', + 'vi-ant-design:code-filled', + 'vi-ant-design:code-outlined', + 'vi-ant-design:code-sandbox-circle-filled', + 'vi-ant-design:code-sandbox-outlined', + 'vi-ant-design:code-sandbox-square-filled', + 'vi-ant-design:code-twotone', + 'vi-ant-design:codepen-circle-filled', + 'vi-ant-design:codepen-circle-outlined', + 'vi-ant-design:codepen-outlined', + 'vi-ant-design:codepen-square-filled', + 'vi-ant-design:coffee-outlined', + 'vi-ant-design:column-height-outlined', + 'vi-ant-design:column-width-outlined', + 'vi-ant-design:comment-outlined', + 'vi-ant-design:compass-filled', + 'vi-ant-design:compass-outlined', + 'vi-ant-design:compass-twotone', + 'vi-ant-design:compress-outlined', + 'vi-ant-design:console-sql-outlined', + 'vi-ant-design:contacts-filled', + 'vi-ant-design:contacts-outlined', + 'vi-ant-design:contacts-twotone', + 'vi-ant-design:container-filled', + 'vi-ant-design:container-outlined', + 'vi-ant-design:container-twotone', + 'vi-ant-design:control-filled', + 'vi-ant-design:control-outlined', + 'vi-ant-design:control-twotone', + 'vi-ant-design:copy-filled', + 'vi-ant-design:copy-outlined', + 'vi-ant-design:copy-twotone', + 'vi-ant-design:copyright-circle-filled', + 'vi-ant-design:copyright-circle-outlined', + 'vi-ant-design:copyright-circle-twotone', + 'vi-ant-design:copyright-outlined', + 'vi-ant-design:copyright-twotone', + 'vi-ant-design:credit-card-filled', + 'vi-ant-design:credit-card-outlined', + 'vi-ant-design:credit-card-twotone', + 'vi-ant-design:crown-filled', + 'vi-ant-design:crown-outlined', + 'vi-ant-design:crown-twotone', + 'vi-ant-design:customer-service-filled', + 'vi-ant-design:customer-service-outlined', + 'vi-ant-design:customer-service-twotone', + 'vi-ant-design:dash-outlined', + 'vi-ant-design:dashboard-filled', + 'vi-ant-design:dashboard-outlined', + 'vi-ant-design:dashboard-twotone', + 'vi-ant-design:database-filled', + 'vi-ant-design:database-outlined', + 'vi-ant-design:database-twotone', + 'vi-ant-design:delete-column-outlined', + 'vi-ant-design:delete-filled', + 'vi-ant-design:delete-outlined', + 'vi-ant-design:delete-row-outlined', + 'vi-ant-design:delete-twotone', + 'vi-ant-design:delivered-procedure-outlined', + 'vi-ant-design:deployment-unit-outlined', + 'vi-ant-design:desktop-outlined', + 'vi-ant-design:diff-filled', + 'vi-ant-design:diff-outlined', + 'vi-ant-design:diff-twotone', + 'vi-ant-design:dingding-outlined', + 'vi-ant-design:dingtalk-circle-filled', + 'vi-ant-design:dingtalk-outlined', + 'vi-ant-design:dingtalk-square-filled', + 'vi-ant-design:disconnect-outlined', + 'vi-ant-design:discord-filled', + 'vi-ant-design:discord-outlined', + 'vi-ant-design:dislike-filled', + 'vi-ant-design:dislike-outlined', + 'vi-ant-design:dislike-twotone', + 'vi-ant-design:docker-outlined', + 'vi-ant-design:dollar-circle-filled', + 'vi-ant-design:dollar-circle-outlined', + 'vi-ant-design:dollar-circle-twotone', + 'vi-ant-design:dollar-outlined', + 'vi-ant-design:dollar-twotone', + 'vi-ant-design:dot-chart-outlined', + 'vi-ant-design:dot-net-outlined', + 'vi-ant-design:double-left-outlined', + 'vi-ant-design:double-right-outlined', + 'vi-ant-design:down-circle-filled', + 'vi-ant-design:down-circle-outlined', + 'vi-ant-design:down-circle-twotone', + 'vi-ant-design:down-outlined', + 'vi-ant-design:down-square-filled', + 'vi-ant-design:down-square-outlined', + 'vi-ant-design:down-square-twotone', + 'vi-ant-design:download-outlined', + 'vi-ant-design:drag-outlined', + 'vi-ant-design:dribbble-circle-filled', + 'vi-ant-design:dribbble-outlined', + 'vi-ant-design:dribbble-square-filled', + 'vi-ant-design:dribbble-square-outlined', + 'vi-ant-design:dropbox-circle-filled', + 'vi-ant-design:dropbox-outlined', + 'vi-ant-design:dropbox-square-filled', + 'vi-ant-design:edit-filled', + 'vi-ant-design:edit-outlined', + 'vi-ant-design:edit-twotone', + 'vi-ant-design:ellipsis-outlined', + 'vi-ant-design:enter-outlined', + 'vi-ant-design:environment-filled', + 'vi-ant-design:environment-outlined', + 'vi-ant-design:environment-twotone', + 'vi-ant-design:euro-circle-filled', + 'vi-ant-design:euro-circle-outlined', + 'vi-ant-design:euro-circle-twotone', + 'vi-ant-design:euro-outlined', + 'vi-ant-design:euro-twotone', + 'vi-ant-design:exception-outlined', + 'vi-ant-design:exclamation-circle-filled', + 'vi-ant-design:exclamation-circle-outlined', + 'vi-ant-design:exclamation-circle-twotone', + 'vi-ant-design:exclamation-outlined', + 'vi-ant-design:expand-alt-outlined', + 'vi-ant-design:expand-outlined', + 'vi-ant-design:experiment-filled', + 'vi-ant-design:experiment-outlined', + 'vi-ant-design:experiment-twotone', + 'vi-ant-design:export-outlined', + 'vi-ant-design:eye-filled', + 'vi-ant-design:eye-invisible-filled', + 'vi-ant-design:eye-invisible-outlined', + 'vi-ant-design:eye-invisible-twotone', + 'vi-ant-design:eye-outlined', + 'vi-ant-design:eye-twotone', + 'vi-ant-design:facebook-filled', + 'vi-ant-design:facebook-outlined', + 'vi-ant-design:fall-outlined', + 'vi-ant-design:fast-backward-filled', + 'vi-ant-design:fast-backward-outlined', + 'vi-ant-design:fast-forward-filled', + 'vi-ant-design:fast-forward-outlined', + 'vi-ant-design:field-binary-outlined', + 'vi-ant-design:field-number-outlined', + 'vi-ant-design:field-string-outlined', + 'vi-ant-design:field-time-outlined', + 'vi-ant-design:file-add-filled', + 'vi-ant-design:file-add-outlined', + 'vi-ant-design:file-add-twotone', + 'vi-ant-design:file-done-outlined', + 'vi-ant-design:file-excel-filled', + 'vi-ant-design:file-excel-outlined', + 'vi-ant-design:file-excel-twotone', + 'vi-ant-design:file-exclamation-filled', + 'vi-ant-design:file-exclamation-outlined', + 'vi-ant-design:file-exclamation-twotone', + 'vi-ant-design:file-filled', + 'vi-ant-design:file-gif-outlined', + 'vi-ant-design:file-image-filled', + 'vi-ant-design:file-image-outlined', + 'vi-ant-design:file-image-twotone', + 'vi-ant-design:file-jpg-outlined', + 'vi-ant-design:file-markdown-filled', + 'vi-ant-design:file-markdown-outlined', + 'vi-ant-design:file-markdown-twotone', + 'vi-ant-design:file-outlined', + 'vi-ant-design:file-pdf-filled', + 'vi-ant-design:file-pdf-outlined', + 'vi-ant-design:file-pdf-twotone', + 'vi-ant-design:file-ppt-filled', + 'vi-ant-design:file-ppt-outlined', + 'vi-ant-design:file-ppt-twotone', + 'vi-ant-design:file-protect-outlined', + 'vi-ant-design:file-search-outlined', + 'vi-ant-design:file-sync-outlined', + 'vi-ant-design:file-text-filled', + 'vi-ant-design:file-text-outlined', + 'vi-ant-design:file-text-twotone', + 'vi-ant-design:file-twotone', + 'vi-ant-design:file-unknown-filled', + 'vi-ant-design:file-unknown-outlined', + 'vi-ant-design:file-unknown-twotone', + 'vi-ant-design:file-word-filled', + 'vi-ant-design:file-word-outlined', + 'vi-ant-design:file-word-twotone', + 'vi-ant-design:file-zip-filled', + 'vi-ant-design:file-zip-outlined', + 'vi-ant-design:file-zip-twotone', + 'vi-ant-design:filter-filled', + 'vi-ant-design:filter-outlined', + 'vi-ant-design:filter-twotone', + 'vi-ant-design:fire-filled', + 'vi-ant-design:fire-outlined', + 'vi-ant-design:fire-twotone', + 'vi-ant-design:flag-filled', + 'vi-ant-design:flag-outlined', + 'vi-ant-design:flag-twotone', + 'vi-ant-design:folder-add-filled', + 'vi-ant-design:folder-add-outlined', + 'vi-ant-design:folder-add-twotone', + 'vi-ant-design:folder-filled', + 'vi-ant-design:folder-open-filled', + 'vi-ant-design:folder-open-outlined', + 'vi-ant-design:folder-open-twotone', + 'vi-ant-design:folder-outlined', + 'vi-ant-design:folder-twotone', + 'vi-ant-design:folder-view-outlined', + 'vi-ant-design:font-colors-outlined', + 'vi-ant-design:font-size-outlined', + 'vi-ant-design:fork-outlined', + 'vi-ant-design:form-outlined', + 'vi-ant-design:format-painter-filled', + 'vi-ant-design:format-painter-outlined', + 'vi-ant-design:forward-filled', + 'vi-ant-design:forward-outlined', + 'vi-ant-design:frown-filled', + 'vi-ant-design:frown-outlined', + 'vi-ant-design:frown-twotone', + 'vi-ant-design:fullscreen-exit-outlined', + 'vi-ant-design:fullscreen-outlined', + 'vi-ant-design:function-outlined', + 'vi-ant-design:fund-filled', + 'vi-ant-design:fund-outlined', + 'vi-ant-design:fund-projection-screen-outlined', + 'vi-ant-design:fund-twotone', + 'vi-ant-design:fund-view-outlined', + 'vi-ant-design:funnel-plot-filled', + 'vi-ant-design:funnel-plot-outlined', + 'vi-ant-design:funnel-plot-twotone', + 'vi-ant-design:gateway-outlined', + 'vi-ant-design:gif-outlined', + 'vi-ant-design:gift-filled', + 'vi-ant-design:gift-outlined', + 'vi-ant-design:gift-twotone', + 'vi-ant-design:github-filled', + 'vi-ant-design:github-outlined', + 'vi-ant-design:gitlab-filled', + 'vi-ant-design:gitlab-outlined', + 'vi-ant-design:global-outlined', + 'vi-ant-design:gold-filled', + 'vi-ant-design:gold-outlined', + 'vi-ant-design:gold-twotone', + 'vi-ant-design:golden-filled', + 'vi-ant-design:google-circle-filled', + 'vi-ant-design:google-outlined', + 'vi-ant-design:google-plus-circle-filled', + 'vi-ant-design:google-plus-outlined', + 'vi-ant-design:google-plus-square-filled', + 'vi-ant-design:google-square-filled', + 'vi-ant-design:group-outlined', + 'vi-ant-design:harmony-o-s-outlined', + 'vi-ant-design:hdd-filled', + 'vi-ant-design:hdd-outlined', + 'vi-ant-design:hdd-twotone', + 'vi-ant-design:heart-filled', + 'vi-ant-design:heart-outlined', + 'vi-ant-design:heart-twotone', + 'vi-ant-design:heat-map-outlined', + 'vi-ant-design:highlight-filled', + 'vi-ant-design:highlight-outlined', + 'vi-ant-design:highlight-twotone', + 'vi-ant-design:history-outlined', + 'vi-ant-design:holder-outlined', + 'vi-ant-design:home-filled', + 'vi-ant-design:home-outlined', + 'vi-ant-design:home-twotone', + 'vi-ant-design:hourglass-filled', + 'vi-ant-design:hourglass-outlined', + 'vi-ant-design:hourglass-twotone', + 'vi-ant-design:html5-filled', + 'vi-ant-design:html5-outlined', + 'vi-ant-design:html5-twotone', + 'vi-ant-design:idcard-filled', + 'vi-ant-design:idcard-outlined', + 'vi-ant-design:idcard-twotone', + 'vi-ant-design:ie-circle-filled', + 'vi-ant-design:ie-outlined', + 'vi-ant-design:ie-square-filled', + 'vi-ant-design:import-outlined', + 'vi-ant-design:inbox-outlined', + 'vi-ant-design:info-circle-filled', + 'vi-ant-design:info-circle-outlined', + 'vi-ant-design:info-circle-twotone', + 'vi-ant-design:info-outlined', + 'vi-ant-design:insert-row-above-outlined', + 'vi-ant-design:insert-row-below-outlined', + 'vi-ant-design:insert-row-left-outlined', + 'vi-ant-design:insert-row-right-outlined', + 'vi-ant-design:instagram-filled', + 'vi-ant-design:instagram-outlined', + 'vi-ant-design:insurance-filled', + 'vi-ant-design:insurance-outlined', + 'vi-ant-design:insurance-twotone', + 'vi-ant-design:interaction-filled', + 'vi-ant-design:interaction-outlined', + 'vi-ant-design:interaction-twotone', + 'vi-ant-design:issues-close-outlined', + 'vi-ant-design:italic-outlined', + 'vi-ant-design:java-outlined', + 'vi-ant-design:java-script-outlined', + 'vi-ant-design:key-outlined', + 'vi-ant-design:kubernetes-outlined', + 'vi-ant-design:laptop-outlined', + 'vi-ant-design:layout-filled', + 'vi-ant-design:layout-outlined', + 'vi-ant-design:layout-twotone', + 'vi-ant-design:left-circle-filled', + 'vi-ant-design:left-circle-outlined', + 'vi-ant-design:left-circle-twotone', + 'vi-ant-design:left-outlined', + 'vi-ant-design:left-square-filled', + 'vi-ant-design:left-square-outlined', + 'vi-ant-design:left-square-twotone', + 'vi-ant-design:like-filled', + 'vi-ant-design:like-outlined', + 'vi-ant-design:like-twotone', + 'vi-ant-design:line-chart-outlined', + 'vi-ant-design:line-height-outlined', + 'vi-ant-design:line-outlined', + 'vi-ant-design:link-outlined', + 'vi-ant-design:linkedin-filled', + 'vi-ant-design:linkedin-outlined', + 'vi-ant-design:linux-outlined', + 'vi-ant-design:loading-3-quarters-outlined', + 'vi-ant-design:loading-outlined', + 'vi-ant-design:lock-filled', + 'vi-ant-design:lock-outlined', + 'vi-ant-design:lock-twotone', + 'vi-ant-design:login-outlined', + 'vi-ant-design:logout-outlined', + 'vi-ant-design:mac-command-filled', + 'vi-ant-design:mac-command-outlined', + 'vi-ant-design:mail-filled', + 'vi-ant-design:mail-outlined', + 'vi-ant-design:mail-twotone', + 'vi-ant-design:man-outlined', + 'vi-ant-design:medicine-box-filled', + 'vi-ant-design:medicine-box-outlined', + 'vi-ant-design:medicine-box-twotone', + 'vi-ant-design:medium-circle-filled', + 'vi-ant-design:medium-outlined', + 'vi-ant-design:medium-square-filled', + 'vi-ant-design:medium-workmark-outlined', + 'vi-ant-design:meh-filled', + 'vi-ant-design:meh-outlined', + 'vi-ant-design:meh-twotone', + 'vi-ant-design:menu-fold-outlined', + 'vi-ant-design:menu-outlined', + 'vi-ant-design:menu-unfold-outlined', + 'vi-ant-design:merge-cells-outlined', + 'vi-ant-design:merge-filled', + 'vi-ant-design:merge-outlined', + 'vi-ant-design:message-filled', + 'vi-ant-design:message-outlined', + 'vi-ant-design:message-twotone', + 'vi-ant-design:minus-circle-filled', + 'vi-ant-design:minus-circle-outlined', + 'vi-ant-design:minus-circle-twotone', + 'vi-ant-design:minus-outlined', + 'vi-ant-design:minus-square-filled', + 'vi-ant-design:minus-square-outlined', + 'vi-ant-design:minus-square-twotone', + 'vi-ant-design:mobile-filled', + 'vi-ant-design:mobile-outlined', + 'vi-ant-design:mobile-twotone', + 'vi-ant-design:money-collect-filled', + 'vi-ant-design:money-collect-outlined', + 'vi-ant-design:money-collect-twotone', + 'vi-ant-design:monitor-outlined', + 'vi-ant-design:moon-filled', + 'vi-ant-design:moon-outlined', + 'vi-ant-design:more-outlined', + 'vi-ant-design:muted-filled', + 'vi-ant-design:muted-outlined', + 'vi-ant-design:node-collapse-outlined', + 'vi-ant-design:node-expand-outlined', + 'vi-ant-design:node-index-outlined', + 'vi-ant-design:notification-filled', + 'vi-ant-design:notification-outlined', + 'vi-ant-design:notification-twotone', + 'vi-ant-design:number-outlined', + 'vi-ant-design:one-to-one-outlined', + 'vi-ant-design:open-a-i-filled', + 'vi-ant-design:open-a-i-outlined', + 'vi-ant-design:ordered-list-outlined', + 'vi-ant-design:paper-clip-outlined', + 'vi-ant-design:partition-outlined', + 'vi-ant-design:pause-circle-filled', + 'vi-ant-design:pause-circle-outlined', + 'vi-ant-design:pause-circle-twotone', + 'vi-ant-design:pause-outlined', + 'vi-ant-design:pay-circle-filled', + 'vi-ant-design:pay-circle-outlined', + 'vi-ant-design:percentage-outlined', + 'vi-ant-design:phone-filled', + 'vi-ant-design:phone-outlined', + 'vi-ant-design:phone-twotone', + 'vi-ant-design:pic-center-outlined', + 'vi-ant-design:pic-left-outlined', + 'vi-ant-design:pic-right-outlined', + 'vi-ant-design:picture-filled', + 'vi-ant-design:picture-outlined', + 'vi-ant-design:picture-twotone', + 'vi-ant-design:pie-chart-filled', + 'vi-ant-design:pie-chart-outlined', + 'vi-ant-design:pie-chart-twotone', + 'vi-ant-design:pinterest-filled', + 'vi-ant-design:pinterest-outlined', + 'vi-ant-design:play-circle-filled', + 'vi-ant-design:play-circle-outlined', + 'vi-ant-design:play-circle-twotone', + 'vi-ant-design:play-square-filled', + 'vi-ant-design:play-square-outlined', + 'vi-ant-design:play-square-twotone', + 'vi-ant-design:plus-circle-filled', + 'vi-ant-design:plus-circle-outlined', + 'vi-ant-design:plus-circle-twotone', + 'vi-ant-design:plus-outlined', + 'vi-ant-design:plus-square-filled', + 'vi-ant-design:plus-square-outlined', + 'vi-ant-design:plus-square-twotone', + 'vi-ant-design:pound-circle-filled', + 'vi-ant-design:pound-circle-outlined', + 'vi-ant-design:pound-circle-twotone', + 'vi-ant-design:pound-outlined', + 'vi-ant-design:poweroff-outlined', + 'vi-ant-design:printer-filled', + 'vi-ant-design:printer-outlined', + 'vi-ant-design:printer-twotone', + 'vi-ant-design:product-filled', + 'vi-ant-design:product-outlined', + 'vi-ant-design:profile-filled', + 'vi-ant-design:profile-outlined', + 'vi-ant-design:profile-twotone', + 'vi-ant-design:project-filled', + 'vi-ant-design:project-outlined', + 'vi-ant-design:project-twotone', + 'vi-ant-design:property-safety-filled', + 'vi-ant-design:property-safety-outlined', + 'vi-ant-design:property-safety-twotone', + 'vi-ant-design:pull-request-outlined', + 'vi-ant-design:pushpin-filled', + 'vi-ant-design:pushpin-outlined', + 'vi-ant-design:pushpin-twotone', + 'vi-ant-design:python-outlined', + 'vi-ant-design:qq-circle-filled', + 'vi-ant-design:qq-outlined', + 'vi-ant-design:qq-square-filled', + 'vi-ant-design:qrcode-outlined', + 'vi-ant-design:question-circle-filled', + 'vi-ant-design:question-circle-outlined', + 'vi-ant-design:question-circle-twotone', + 'vi-ant-design:question-outlined', + 'vi-ant-design:radar-chart-outlined', + 'vi-ant-design:radius-bottomleft-outlined', + 'vi-ant-design:radius-bottomright-outlined', + 'vi-ant-design:radius-setting-outlined', + 'vi-ant-design:radius-upleft-outlined', + 'vi-ant-design:radius-upright-outlined', + 'vi-ant-design:read-filled', + 'vi-ant-design:read-outlined', + 'vi-ant-design:reconciliation-filled', + 'vi-ant-design:reconciliation-outlined', + 'vi-ant-design:reconciliation-twotone', + 'vi-ant-design:red-envelope-filled', + 'vi-ant-design:red-envelope-outlined', + 'vi-ant-design:red-envelope-twotone', + 'vi-ant-design:reddit-circle-filled', + 'vi-ant-design:reddit-outlined', + 'vi-ant-design:reddit-square-filled', + 'vi-ant-design:redo-outlined', + 'vi-ant-design:reload-outlined', + 'vi-ant-design:rest-filled', + 'vi-ant-design:rest-outlined', + 'vi-ant-design:rest-twotone', + 'vi-ant-design:retweet-outlined', + 'vi-ant-design:right-circle-filled', + 'vi-ant-design:right-circle-outlined', + 'vi-ant-design:right-circle-twotone', + 'vi-ant-design:right-outlined', + 'vi-ant-design:right-square-filled', + 'vi-ant-design:right-square-outlined', + 'vi-ant-design:right-square-twotone', + 'vi-ant-design:rise-outlined', + 'vi-ant-design:robot-filled', + 'vi-ant-design:robot-outlined', + 'vi-ant-design:rocket-filled', + 'vi-ant-design:rocket-outlined', + 'vi-ant-design:rocket-twotone', + 'vi-ant-design:rollback-outlined', + 'vi-ant-design:rotate-left-outlined', + 'vi-ant-design:rotate-right-outlined', + 'vi-ant-design:ruby-outlined', + 'vi-ant-design:safety-certificate-filled', + 'vi-ant-design:safety-certificate-outlined', + 'vi-ant-design:safety-certificate-twotone', + 'vi-ant-design:safety-outlined', + 'vi-ant-design:save-filled', + 'vi-ant-design:save-outlined', + 'vi-ant-design:save-twotone', + 'vi-ant-design:scan-outlined', + 'vi-ant-design:schedule-filled', + 'vi-ant-design:schedule-outlined', + 'vi-ant-design:schedule-twotone', + 'vi-ant-design:scissor-outlined', + 'vi-ant-design:search-outlined', + 'vi-ant-design:security-scan-filled', + 'vi-ant-design:security-scan-outlined', + 'vi-ant-design:security-scan-twotone', + 'vi-ant-design:select-outlined', + 'vi-ant-design:send-outlined', + 'vi-ant-design:setting-filled', + 'vi-ant-design:setting-outlined', + 'vi-ant-design:setting-twotone', + 'vi-ant-design:shake-outlined', + 'vi-ant-design:share-alt-outlined', + 'vi-ant-design:shop-filled', + 'vi-ant-design:shop-outlined', + 'vi-ant-design:shop-twotone', + 'vi-ant-design:shopping-cart-outlined', + 'vi-ant-design:shopping-filled', + 'vi-ant-design:shopping-outlined', + 'vi-ant-design:shopping-twotone', + 'vi-ant-design:shrink-outlined', + 'vi-ant-design:signal-filled', + 'vi-ant-design:signature-filled', + 'vi-ant-design:signature-outlined', + 'vi-ant-design:sisternode-outlined', + 'vi-ant-design:sketch-circle-filled', + 'vi-ant-design:sketch-outlined', + 'vi-ant-design:sketch-square-filled', + 'vi-ant-design:skin-filled', + 'vi-ant-design:skin-outlined', + 'vi-ant-design:skin-twotone', + 'vi-ant-design:skype-filled', + 'vi-ant-design:skype-outlined', + 'vi-ant-design:slack-circle-filled', + 'vi-ant-design:slack-outlined', + 'vi-ant-design:slack-square-filled', + 'vi-ant-design:slack-square-outlined', + 'vi-ant-design:sliders-filled', + 'vi-ant-design:sliders-outlined', + 'vi-ant-design:sliders-twotone', + 'vi-ant-design:small-dash-outlined', + 'vi-ant-design:smile-filled', + 'vi-ant-design:smile-outlined', + 'vi-ant-design:smile-twotone', + 'vi-ant-design:snippets-filled', + 'vi-ant-design:snippets-outlined', + 'vi-ant-design:snippets-twotone', + 'vi-ant-design:solution-outlined', + 'vi-ant-design:sort-ascending-outlined', + 'vi-ant-design:sort-descending-outlined', + 'vi-ant-design:sound-filled', + 'vi-ant-design:sound-outlined', + 'vi-ant-design:sound-twotone', + 'vi-ant-design:split-cells-outlined', + 'vi-ant-design:spotify-filled', + 'vi-ant-design:spotify-outlined', + 'vi-ant-design:star-filled', + 'vi-ant-design:star-outlined', + 'vi-ant-design:star-twotone', + 'vi-ant-design:step-backward-filled', + 'vi-ant-design:step-backward-outlined', + 'vi-ant-design:step-forward-filled', + 'vi-ant-design:step-forward-outlined', + 'vi-ant-design:stock-outlined', + 'vi-ant-design:stop-filled', + 'vi-ant-design:stop-outlined', + 'vi-ant-design:stop-twotone', + 'vi-ant-design:strikethrough-outlined', + 'vi-ant-design:subnode-outlined', + 'vi-ant-design:sun-filled', + 'vi-ant-design:sun-outlined', + 'vi-ant-design:swap-left-outlined', + 'vi-ant-design:swap-outlined', + 'vi-ant-design:swap-right-outlined', + 'vi-ant-design:switcher-filled', + 'vi-ant-design:switcher-outlined', + 'vi-ant-design:switcher-twotone', + 'vi-ant-design:sync-outlined', + 'vi-ant-design:table-outlined', + 'vi-ant-design:tablet-filled', + 'vi-ant-design:tablet-outlined', + 'vi-ant-design:tablet-twotone', + 'vi-ant-design:tag-filled', + 'vi-ant-design:tag-outlined', + 'vi-ant-design:tag-twotone', + 'vi-ant-design:tags-filled', + 'vi-ant-design:tags-outlined', + 'vi-ant-design:tags-twotone', + 'vi-ant-design:taobao-circle-filled', + 'vi-ant-design:taobao-circle-outlined', + 'vi-ant-design:taobao-outlined', + 'vi-ant-design:taobao-square-filled', + 'vi-ant-design:team-outlined', + 'vi-ant-design:thunderbolt-filled', + 'vi-ant-design:thunderbolt-outlined', + 'vi-ant-design:thunderbolt-twotone', + 'vi-ant-design:tik-tok-filled', + 'vi-ant-design:tik-tok-outlined', + 'vi-ant-design:to-top-outlined', + 'vi-ant-design:tool-filled', + 'vi-ant-design:tool-outlined', + 'vi-ant-design:tool-twotone', + 'vi-ant-design:trademark-circle-filled', + 'vi-ant-design:trademark-circle-outlined', + 'vi-ant-design:trademark-circle-twotone', + 'vi-ant-design:trademark-outlined', + 'vi-ant-design:transaction-outlined', + 'vi-ant-design:translation-outlined', + 'vi-ant-design:trophy-filled', + 'vi-ant-design:trophy-outlined', + 'vi-ant-design:trophy-twotone', + 'vi-ant-design:truck-filled', + 'vi-ant-design:truck-outlined', + 'vi-ant-design:twitch-outlined', + 'vi-ant-design:twitter-circle-filled', + 'vi-ant-design:twitter-outlined', + 'vi-ant-design:twitter-square-filled', + 'vi-ant-design:underline-outlined', + 'vi-ant-design:undo-outlined', + 'vi-ant-design:ungroup-outlined', + 'vi-ant-design:unlock-filled', + 'vi-ant-design:unlock-outlined', + 'vi-ant-design:unlock-twotone', + 'vi-ant-design:unordered-list-outlined', + 'vi-ant-design:up-circle-filled', + 'vi-ant-design:up-circle-outlined', + 'vi-ant-design:up-circle-twotone', + 'vi-ant-design:up-outlined', + 'vi-ant-design:up-square-filled', + 'vi-ant-design:up-square-outlined', + 'vi-ant-design:up-square-twotone', + 'vi-ant-design:upload-outlined', + 'vi-ant-design:usb-filled', + 'vi-ant-design:usb-outlined', + 'vi-ant-design:usb-twotone', + 'vi-ant-design:user-add-outlined', + 'vi-ant-design:user-delete-outlined', + 'vi-ant-design:user-outlined', + 'vi-ant-design:user-switch-outlined', + 'vi-ant-design:usergroup-add-outlined', + 'vi-ant-design:usergroup-delete-outlined', + 'vi-ant-design:verified-outlined', + 'vi-ant-design:vertical-align-bottom-outlined', + 'vi-ant-design:vertical-align-middle-outlined', + 'vi-ant-design:vertical-align-top-outlined', + 'vi-ant-design:vertical-left-outlined', + 'vi-ant-design:vertical-right-outlined', + 'vi-ant-design:video-camera-add-outlined', + 'vi-ant-design:video-camera-filled', + 'vi-ant-design:video-camera-outlined', + 'vi-ant-design:video-camera-twotone', + 'vi-ant-design:wallet-filled', + 'vi-ant-design:wallet-outlined', + 'vi-ant-design:wallet-twotone', + 'vi-ant-design:warning-filled', + 'vi-ant-design:warning-outlined', + 'vi-ant-design:warning-twotone', + 'vi-ant-design:wechat-filled', + 'vi-ant-design:wechat-outlined', + 'vi-ant-design:wechat-work-filled', + 'vi-ant-design:wechat-work-outlined', + 'vi-ant-design:weibo-circle-filled', + 'vi-ant-design:weibo-circle-outlined', + 'vi-ant-design:weibo-outlined', + 'vi-ant-design:weibo-square-filled', + 'vi-ant-design:weibo-square-outlined', + 'vi-ant-design:whats-app-outlined', + 'vi-ant-design:wifi-outlined', + 'vi-ant-design:windows-filled', + 'vi-ant-design:windows-outlined', + 'vi-ant-design:woman-outlined', + 'vi-ant-design:x-filled', + 'vi-ant-design:x-outlined', + 'vi-ant-design:yahoo-filled', + 'vi-ant-design:yahoo-outlined', + 'vi-ant-design:youtube-filled', + 'vi-ant-design:youtube-outlined', + 'vi-ant-design:yuque-filled', + 'vi-ant-design:yuque-outlined', + 'vi-ant-design:zhihu-circle-filled', + 'vi-ant-design:zhihu-outlined', + 'vi-ant-design:zhihu-square-filled', + 'vi-ant-design:zoom-in-outlined', + 'vi-ant-design:zoom-out-outlined' + ] +} diff --git a/src/components/IconPicker/src/data/icons.ep.ts b/src/components/IconPicker/src/data/icons.ep.ts new file mode 100644 index 000000000..b3918beac --- /dev/null +++ b/src/components/IconPicker/src/data/icons.ep.ts @@ -0,0 +1,299 @@ +export default { + name: 'Element Plus', + prefix: 'vi-ep', + icons: [ + 'vi-ep:add-location', + 'vi-ep:aim', + 'vi-ep:alarm-clock', + 'vi-ep:apple', + 'vi-ep:arrow-down', + 'vi-ep:arrow-down-bold', + 'vi-ep:arrow-left', + 'vi-ep:arrow-left-bold', + 'vi-ep:arrow-right', + 'vi-ep:arrow-right-bold', + 'vi-ep:arrow-up', + 'vi-ep:arrow-up-bold', + 'vi-ep:avatar', + 'vi-ep:back', + 'vi-ep:baseball', + 'vi-ep:basketball', + 'vi-ep:bell', + 'vi-ep:bell-filled', + 'vi-ep:bicycle', + 'vi-ep:bottom', + 'vi-ep:bottom-left', + 'vi-ep:bottom-right', + 'vi-ep:bowl', + 'vi-ep:box', + 'vi-ep:briefcase', + 'vi-ep:brush', + 'vi-ep:brush-filled', + 'vi-ep:burger', + 'vi-ep:calendar', + 'vi-ep:camera', + 'vi-ep:camera-filled', + 'vi-ep:caret-bottom', + 'vi-ep:caret-left', + 'vi-ep:caret-right', + 'vi-ep:caret-top', + 'vi-ep:cellphone', + 'vi-ep:chat-dot-round', + 'vi-ep:chat-dot-square', + 'vi-ep:chat-line-round', + 'vi-ep:chat-line-square', + 'vi-ep:chat-round', + 'vi-ep:chat-square', + 'vi-ep:check', + 'vi-ep:checked', + 'vi-ep:cherry', + 'vi-ep:chicken', + 'vi-ep:chrome-filled', + 'vi-ep:circle-check', + 'vi-ep:circle-check-filled', + 'vi-ep:circle-close', + 'vi-ep:circle-close-filled', + 'vi-ep:circle-plus', + 'vi-ep:circle-plus-filled', + 'vi-ep:clock', + 'vi-ep:close', + 'vi-ep:close-bold', + 'vi-ep:cloudy', + 'vi-ep:coffee', + 'vi-ep:coffee-cup', + 'vi-ep:coin', + 'vi-ep:cold-drink', + 'vi-ep:collection', + 'vi-ep:collection-tag', + 'vi-ep:comment', + 'vi-ep:compass', + 'vi-ep:connection', + 'vi-ep:coordinate', + 'vi-ep:copy-document', + 'vi-ep:cpu', + 'vi-ep:credit-card', + 'vi-ep:crop', + 'vi-ep:d-arrow-left', + 'vi-ep:d-arrow-right', + 'vi-ep:d-caret', + 'vi-ep:data-analysis', + 'vi-ep:data-board', + 'vi-ep:data-line', + 'vi-ep:delete', + 'vi-ep:delete-filled', + 'vi-ep:delete-location', + 'vi-ep:dessert', + 'vi-ep:discount', + 'vi-ep:dish', + 'vi-ep:dish-dot', + 'vi-ep:document', + 'vi-ep:document-add', + 'vi-ep:document-checked', + 'vi-ep:document-copy', + 'vi-ep:document-delete', + 'vi-ep:document-remove', + 'vi-ep:download', + 'vi-ep:drizzling', + 'vi-ep:edit', + 'vi-ep:edit-pen', + 'vi-ep:eleme', + 'vi-ep:eleme-filled', + 'vi-ep:element-plus', + 'vi-ep:expand', + 'vi-ep:failed', + 'vi-ep:female', + 'vi-ep:files', + 'vi-ep:film', + 'vi-ep:filter', + 'vi-ep:finished', + 'vi-ep:first-aid-kit', + 'vi-ep:flag', + 'vi-ep:fold', + 'vi-ep:folder', + 'vi-ep:folder-add', + 'vi-ep:folder-checked', + 'vi-ep:folder-delete', + 'vi-ep:folder-opened', + 'vi-ep:folder-remove', + 'vi-ep:food', + 'vi-ep:football', + 'vi-ep:fork-spoon', + 'vi-ep:fries', + 'vi-ep:full-screen', + 'vi-ep:goblet', + 'vi-ep:goblet-full', + 'vi-ep:goblet-square', + 'vi-ep:goblet-square-full', + 'vi-ep:gold-medal', + 'vi-ep:goods', + 'vi-ep:goods-filled', + 'vi-ep:grape', + 'vi-ep:grid', + 'vi-ep:guide', + 'vi-ep:handbag', + 'vi-ep:headset', + 'vi-ep:help', + 'vi-ep:help-filled', + 'vi-ep:hide', + 'vi-ep:histogram', + 'vi-ep:home-filled', + 'vi-ep:hot-water', + 'vi-ep:house', + 'vi-ep:ice-cream', + 'vi-ep:ice-cream-round', + 'vi-ep:ice-cream-square', + 'vi-ep:ice-drink', + 'vi-ep:ice-tea', + 'vi-ep:info-filled', + 'vi-ep:iphone', + 'vi-ep:key', + 'vi-ep:knife-fork', + 'vi-ep:lightning', + 'vi-ep:link', + 'vi-ep:list', + 'vi-ep:loading', + 'vi-ep:location', + 'vi-ep:location-filled', + 'vi-ep:location-information', + 'vi-ep:lock', + 'vi-ep:lollipop', + 'vi-ep:magic-stick', + 'vi-ep:magnet', + 'vi-ep:male', + 'vi-ep:management', + 'vi-ep:map-location', + 'vi-ep:medal', + 'vi-ep:memo', + 'vi-ep:menu', + 'vi-ep:message', + 'vi-ep:message-box', + 'vi-ep:mic', + 'vi-ep:microphone', + 'vi-ep:milk-tea', + 'vi-ep:minus', + 'vi-ep:money', + 'vi-ep:monitor', + 'vi-ep:moon', + 'vi-ep:moon-night', + 'vi-ep:more', + 'vi-ep:more-filled', + 'vi-ep:mostly-cloudy', + 'vi-ep:mouse', + 'vi-ep:mug', + 'vi-ep:mute', + 'vi-ep:mute-notification', + 'vi-ep:no-smoking', + 'vi-ep:notebook', + 'vi-ep:notification', + 'vi-ep:odometer', + 'vi-ep:office-building', + 'vi-ep:open', + 'vi-ep:operation', + 'vi-ep:opportunity', + 'vi-ep:orange', + 'vi-ep:paperclip', + 'vi-ep:partly-cloudy', + 'vi-ep:pear', + 'vi-ep:phone', + 'vi-ep:phone-filled', + 'vi-ep:picture', + 'vi-ep:picture-filled', + 'vi-ep:picture-rounded', + 'vi-ep:pie-chart', + 'vi-ep:place', + 'vi-ep:platform', + 'vi-ep:plus', + 'vi-ep:pointer', + 'vi-ep:position', + 'vi-ep:postcard', + 'vi-ep:pouring', + 'vi-ep:present', + 'vi-ep:price-tag', + 'vi-ep:printer', + 'vi-ep:promotion', + 'vi-ep:quartz-watch', + 'vi-ep:question-filled', + 'vi-ep:rank', + 'vi-ep:reading', + 'vi-ep:reading-lamp', + 'vi-ep:refresh', + 'vi-ep:refresh-left', + 'vi-ep:refresh-right', + 'vi-ep:refrigerator', + 'vi-ep:remove', + 'vi-ep:remove-filled', + 'vi-ep:right', + 'vi-ep:scale-to-original', + 'vi-ep:school', + 'vi-ep:scissor', + 'vi-ep:search', + 'vi-ep:select', + 'vi-ep:sell', + 'vi-ep:semi-select', + 'vi-ep:service', + 'vi-ep:set-up', + 'vi-ep:setting', + 'vi-ep:share', + 'vi-ep:ship', + 'vi-ep:shop', + 'vi-ep:shopping-bag', + 'vi-ep:shopping-cart', + 'vi-ep:shopping-cart-full', + 'vi-ep:shopping-trolley', + 'vi-ep:smoking', + 'vi-ep:soccer', + 'vi-ep:sold-out', + 'vi-ep:sort', + 'vi-ep:sort-down', + 'vi-ep:sort-up', + 'vi-ep:stamp', + 'vi-ep:star', + 'vi-ep:star-filled', + 'vi-ep:stopwatch', + 'vi-ep:success-filled', + 'vi-ep:sugar', + 'vi-ep:suitcase', + 'vi-ep:suitcase-line', + 'vi-ep:sunny', + 'vi-ep:sunrise', + 'vi-ep:sunset', + 'vi-ep:switch', + 'vi-ep:switch-button', + 'vi-ep:switch-filled', + 'vi-ep:takeaway-box', + 'vi-ep:ticket', + 'vi-ep:tickets', + 'vi-ep:timer', + 'vi-ep:toilet-paper', + 'vi-ep:tools', + 'vi-ep:top', + 'vi-ep:top-left', + 'vi-ep:top-right', + 'vi-ep:trend-charts', + 'vi-ep:trophy', + 'vi-ep:trophy-base', + 'vi-ep:turn-off', + 'vi-ep:umbrella', + 'vi-ep:unlock', + 'vi-ep:upload', + 'vi-ep:upload-filled', + 'vi-ep:user', + 'vi-ep:user-filled', + 'vi-ep:van', + 'vi-ep:video-camera', + 'vi-ep:video-camera-filled', + 'vi-ep:video-pause', + 'vi-ep:video-play', + 'vi-ep:view', + 'vi-ep:wallet', + 'vi-ep:wallet-filled', + 'vi-ep:warn-triangle-filled', + 'vi-ep:warning', + 'vi-ep:warning-filled', + 'vi-ep:watch', + 'vi-ep:watermelon', + 'vi-ep:wind-power', + 'vi-ep:zoom-in', + 'vi-ep:zoom-out' + ] +} diff --git a/src/components/IconPicker/src/data/icons.tdesign.ts b/src/components/IconPicker/src/data/icons.tdesign.ts new file mode 100644 index 000000000..77b298b1d --- /dev/null +++ b/src/components/IconPicker/src/data/icons.tdesign.ts @@ -0,0 +1,1209 @@ +export default { + name: 'TDesign Icons', + prefix: 'vi-tdesign', + icons: [ + 'vi-tdesign:activity', + 'vi-tdesign:add', + 'vi-tdesign:add-and-subtract', + 'vi-tdesign:add-circle', + 'vi-tdesign:add-rectangle', + 'vi-tdesign:address-book', + 'vi-tdesign:adjustment', + 'vi-tdesign:airplay-wave', + 'vi-tdesign:alarm', + 'vi-tdesign:alarm-add', + 'vi-tdesign:alarm-off', + 'vi-tdesign:align-top', + 'vi-tdesign:align-vertical', + 'vi-tdesign:alpha', + 'vi-tdesign:analytics', + 'vi-tdesign:anchor', + 'vi-tdesign:angry', + 'vi-tdesign:animation', + 'vi-tdesign:animation-1', + 'vi-tdesign:anticlockwise', + 'vi-tdesign:api', + 'vi-tdesign:app', + 'vi-tdesign:apple', + 'vi-tdesign:application', + 'vi-tdesign:architecture-hui-style', + 'vi-tdesign:archway', + 'vi-tdesign:archway-1', + 'vi-tdesign:arrow-down', + 'vi-tdesign:arrow-down-circle', + 'vi-tdesign:arrow-down-rectangle', + 'vi-tdesign:arrow-left', + 'vi-tdesign:arrow-left-circle', + 'vi-tdesign:arrow-left-down', + 'vi-tdesign:arrow-left-down-circle', + 'vi-tdesign:arrow-left-right-1', + 'vi-tdesign:arrow-left-right-2', + 'vi-tdesign:arrow-left-right-3', + 'vi-tdesign:arrow-left-right-circle', + 'vi-tdesign:arrow-left-up', + 'vi-tdesign:arrow-left-up-circle', + 'vi-tdesign:arrow-right', + 'vi-tdesign:arrow-right-circle', + 'vi-tdesign:arrow-right-down', + 'vi-tdesign:arrow-right-down-circle', + 'vi-tdesign:arrow-right-up', + 'vi-tdesign:arrow-right-up-circle', + 'vi-tdesign:arrow-triangle-down', + 'vi-tdesign:arrow-triangle-down-filled', + 'vi-tdesign:arrow-triangle-up', + 'vi-tdesign:arrow-triangle-up-filled', + 'vi-tdesign:arrow-up', + 'vi-tdesign:arrow-up-circle', + 'vi-tdesign:arrow-up-down-1', + 'vi-tdesign:arrow-up-down-2', + 'vi-tdesign:arrow-up-down-3', + 'vi-tdesign:arrow-up-down-circle', + 'vi-tdesign:artboard', + 'vi-tdesign:article', + 'vi-tdesign:assignment', + 'vi-tdesign:assignment-checked', + 'vi-tdesign:assignment-code', + 'vi-tdesign:assignment-error', + 'vi-tdesign:assignment-user', + 'vi-tdesign:attach', + 'vi-tdesign:attic', + 'vi-tdesign:attic-1', + 'vi-tdesign:audio', + 'vi-tdesign:awkward', + 'vi-tdesign:backtop', + 'vi-tdesign:backtop-rectangle', + 'vi-tdesign:backup', + 'vi-tdesign:backward', + 'vi-tdesign:bad-laugh', + 'vi-tdesign:bamboo-shoot', + 'vi-tdesign:banana', + 'vi-tdesign:barbecue', + 'vi-tdesign:barcode', + 'vi-tdesign:barcode-1', + 'vi-tdesign:base-station', + 'vi-tdesign:battery', + 'vi-tdesign:battery-add', + 'vi-tdesign:battery-charging', + 'vi-tdesign:battery-low', + 'vi-tdesign:bean', + 'vi-tdesign:beer', + 'vi-tdesign:beta', + 'vi-tdesign:bifurcate', + 'vi-tdesign:bill', + 'vi-tdesign:blockchain', + 'vi-tdesign:bluetooth', + 'vi-tdesign:bone', + 'vi-tdesign:book', + 'vi-tdesign:book-open', + 'vi-tdesign:bookmark', + 'vi-tdesign:bookmark-add', + 'vi-tdesign:bookmark-checked', + 'vi-tdesign:bookmark-double', + 'vi-tdesign:bookmark-minus', + 'vi-tdesign:braces', + 'vi-tdesign:brackets', + 'vi-tdesign:bread', + 'vi-tdesign:bridge', + 'vi-tdesign:bridge-1', + 'vi-tdesign:bridge-2', + 'vi-tdesign:bridge-3', + 'vi-tdesign:bridge-4', + 'vi-tdesign:bridge-5', + 'vi-tdesign:bridge-6', + 'vi-tdesign:brightness', + 'vi-tdesign:brightness-1', + 'vi-tdesign:broccoli', + 'vi-tdesign:browse', + 'vi-tdesign:browse-gallery', + 'vi-tdesign:browse-off', + 'vi-tdesign:brush', + 'vi-tdesign:bug', + 'vi-tdesign:bug-report', + 'vi-tdesign:building', + 'vi-tdesign:building-1', + 'vi-tdesign:building-2', + 'vi-tdesign:building-3', + 'vi-tdesign:building-4', + 'vi-tdesign:building-5', + 'vi-tdesign:bulletpoint', + 'vi-tdesign:button', + 'vi-tdesign:cabbage', + 'vi-tdesign:cake', + 'vi-tdesign:calculation', + 'vi-tdesign:calculation-1', + 'vi-tdesign:calculator', + 'vi-tdesign:calculator-1', + 'vi-tdesign:calendar', + 'vi-tdesign:calendar-1', + 'vi-tdesign:calendar-2', + 'vi-tdesign:calendar-edit', + 'vi-tdesign:calendar-event', + 'vi-tdesign:call', + 'vi-tdesign:call-1', + 'vi-tdesign:call-cancel', + 'vi-tdesign:call-forwarded', + 'vi-tdesign:call-incoming', + 'vi-tdesign:call-off', + 'vi-tdesign:calm', + 'vi-tdesign:calm-1', + 'vi-tdesign:camera', + 'vi-tdesign:camera-1', + 'vi-tdesign:camera-2', + 'vi-tdesign:camera-off', + 'vi-tdesign:candy', + 'vi-tdesign:card', + 'vi-tdesign:cardmembership', + 'vi-tdesign:caret-down', + 'vi-tdesign:caret-down-small', + 'vi-tdesign:caret-left', + 'vi-tdesign:caret-left-small', + 'vi-tdesign:caret-right', + 'vi-tdesign:caret-right-small', + 'vi-tdesign:caret-up', + 'vi-tdesign:caret-up-small', + 'vi-tdesign:cart', + 'vi-tdesign:cart-add', + 'vi-tdesign:cast', + 'vi-tdesign:castle', + 'vi-tdesign:castle-1', + 'vi-tdesign:castle-2', + 'vi-tdesign:castle-3', + 'vi-tdesign:castle-4', + 'vi-tdesign:castle-5', + 'vi-tdesign:castle-6', + 'vi-tdesign:castle-7', + 'vi-tdesign:cat', + 'vi-tdesign:catalog', + 'vi-tdesign:cd', + 'vi-tdesign:celsius', + 'vi-tdesign:center-focus-strong', + 'vi-tdesign:centimeter', + 'vi-tdesign:certificate', + 'vi-tdesign:certificate-1', + 'vi-tdesign:chart', + 'vi-tdesign:chart-3d', + 'vi-tdesign:chart-add', + 'vi-tdesign:chart-analytics', + 'vi-tdesign:chart-area', + 'vi-tdesign:chart-area-multi', + 'vi-tdesign:chart-bar', + 'vi-tdesign:chart-bubble', + 'vi-tdesign:chart-colum', + 'vi-tdesign:chart-combo', + 'vi-tdesign:chart-line', + 'vi-tdesign:chart-line-data', + 'vi-tdesign:chart-line-data-1', + 'vi-tdesign:chart-line-multi', + 'vi-tdesign:chart-maximum', + 'vi-tdesign:chart-median', + 'vi-tdesign:chart-minimum', + 'vi-tdesign:chart-pie', + 'vi-tdesign:chart-radar', + 'vi-tdesign:chart-radial', + 'vi-tdesign:chart-ring', + 'vi-tdesign:chart-ring-1', + 'vi-tdesign:chart-scatter', + 'vi-tdesign:chart-stacked', + 'vi-tdesign:chat', + 'vi-tdesign:chat-add', + 'vi-tdesign:chat-bubble', + 'vi-tdesign:chat-bubble-1', + 'vi-tdesign:chat-bubble-add', + 'vi-tdesign:chat-bubble-error', + 'vi-tdesign:chat-bubble-help', + 'vi-tdesign:chat-bubble-history', + 'vi-tdesign:chat-bubble-locked', + 'vi-tdesign:chat-bubble-smile', + 'vi-tdesign:chat-checked', + 'vi-tdesign:chat-clear', + 'vi-tdesign:chat-double', + 'vi-tdesign:chat-error', + 'vi-tdesign:chat-heart', + 'vi-tdesign:chat-message', + 'vi-tdesign:chat-off', + 'vi-tdesign:chat-poll', + 'vi-tdesign:chat-setting', + 'vi-tdesign:check', + 'vi-tdesign:check-circle', + 'vi-tdesign:check-circle-filled', + 'vi-tdesign:check-double', + 'vi-tdesign:check-rectangle', + 'vi-tdesign:check-rectangle-filled', + 'vi-tdesign:cheese', + 'vi-tdesign:cherry', + 'vi-tdesign:chevron-down', + 'vi-tdesign:chevron-down-circle', + 'vi-tdesign:chevron-down-double', + 'vi-tdesign:chevron-down-double-s', + 'vi-tdesign:chevron-down-rectangle', + 'vi-tdesign:chevron-down-s', + 'vi-tdesign:chevron-left', + 'vi-tdesign:chevron-left-circle', + 'vi-tdesign:chevron-left-double', + 'vi-tdesign:chevron-left-double-s', + 'vi-tdesign:chevron-left-rectangle', + 'vi-tdesign:chevron-left-s', + 'vi-tdesign:chevron-right', + 'vi-tdesign:chevron-right-circle', + 'vi-tdesign:chevron-right-double', + 'vi-tdesign:chevron-right-double-s', + 'vi-tdesign:chevron-right-rectangle', + 'vi-tdesign:chevron-right-s', + 'vi-tdesign:chevron-up', + 'vi-tdesign:chevron-up-circle', + 'vi-tdesign:chevron-up-double', + 'vi-tdesign:chevron-up-double-s', + 'vi-tdesign:chevron-up-rectangle', + 'vi-tdesign:chevron-up-s', + 'vi-tdesign:chicken', + 'vi-tdesign:chili', + 'vi-tdesign:chimney', + 'vi-tdesign:chimney-1', + 'vi-tdesign:chimney-2', + 'vi-tdesign:chinese-cabbage', + 'vi-tdesign:church', + 'vi-tdesign:circle', + 'vi-tdesign:city', + 'vi-tdesign:city-1', + 'vi-tdesign:city-10', + 'vi-tdesign:city-11', + 'vi-tdesign:city-12', + 'vi-tdesign:city-13', + 'vi-tdesign:city-14', + 'vi-tdesign:city-15', + 'vi-tdesign:city-2', + 'vi-tdesign:city-3', + 'vi-tdesign:city-4', + 'vi-tdesign:city-5', + 'vi-tdesign:city-6', + 'vi-tdesign:city-7', + 'vi-tdesign:city-8', + 'vi-tdesign:city-9', + 'vi-tdesign:city-ancient', + 'vi-tdesign:city-ancient-1', + 'vi-tdesign:city-ancient-2', + 'vi-tdesign:clear', + 'vi-tdesign:clear-formatting', + 'vi-tdesign:clear-formatting-1', + 'vi-tdesign:close', + 'vi-tdesign:close-circle', + 'vi-tdesign:close-circle-filled', + 'vi-tdesign:close-octagon', + 'vi-tdesign:close-rectangle', + 'vi-tdesign:cloud', + 'vi-tdesign:cloud-download', + 'vi-tdesign:cloud-upload', + 'vi-tdesign:cloudy-day', + 'vi-tdesign:cloudy-night', + 'vi-tdesign:cloudy-night-rain', + 'vi-tdesign:cloudy-rain', + 'vi-tdesign:cloudy-sunny', + 'vi-tdesign:code', + 'vi-tdesign:code-1', + 'vi-tdesign:code-off', + 'vi-tdesign:cola', + 'vi-tdesign:collage', + 'vi-tdesign:collection', + 'vi-tdesign:color-invert', + 'vi-tdesign:combination', + 'vi-tdesign:command', + 'vi-tdesign:compass', + 'vi-tdesign:compass-1', + 'vi-tdesign:component-breadcrumb', + 'vi-tdesign:component-checkbox', + 'vi-tdesign:component-divider-horizontal', + 'vi-tdesign:component-divider-vertical', + 'vi-tdesign:component-dropdown', + 'vi-tdesign:component-grid', + 'vi-tdesign:component-input', + 'vi-tdesign:component-layout', + 'vi-tdesign:component-radio', + 'vi-tdesign:component-space', + 'vi-tdesign:component-steps', + 'vi-tdesign:component-switch', + 'vi-tdesign:constraint', + 'vi-tdesign:contrast', + 'vi-tdesign:contrast-1', + 'vi-tdesign:control-platform', + 'vi-tdesign:cooperate', + 'vi-tdesign:coordinate-system', + 'vi-tdesign:copy', + 'vi-tdesign:copyright', + 'vi-tdesign:corn', + 'vi-tdesign:coupon', + 'vi-tdesign:course', + 'vi-tdesign:cpu', + 'vi-tdesign:crack', + 'vi-tdesign:creditcard', + 'vi-tdesign:creditcard-add', + 'vi-tdesign:creditcard-off', + 'vi-tdesign:crooked-smile', + 'vi-tdesign:cry-and-laugh', + 'vi-tdesign:cry-loudly', + 'vi-tdesign:css3', + 'vi-tdesign:cucumber', + 'vi-tdesign:currency-exchange', + 'vi-tdesign:cursor', + 'vi-tdesign:curtain', + 'vi-tdesign:curve', + 'vi-tdesign:cut', + 'vi-tdesign:cut-1', + 'vi-tdesign:dam', + 'vi-tdesign:dam-1', + 'vi-tdesign:dam-2', + 'vi-tdesign:dam-3', + 'vi-tdesign:dam-4', + 'vi-tdesign:dam-5', + 'vi-tdesign:dam-6', + 'vi-tdesign:dam-7', + 'vi-tdesign:dart-board', + 'vi-tdesign:dashboard', + 'vi-tdesign:dashboard-1', + 'vi-tdesign:data', + 'vi-tdesign:data-base', + 'vi-tdesign:data-checked', + 'vi-tdesign:data-display', + 'vi-tdesign:data-error', + 'vi-tdesign:data-search', + 'vi-tdesign:delete', + 'vi-tdesign:delete-1', + 'vi-tdesign:delete-time', + 'vi-tdesign:delta', + 'vi-tdesign:depressed', + 'vi-tdesign:desktop', + 'vi-tdesign:desktop-1', + 'vi-tdesign:despise', + 'vi-tdesign:device', + 'vi-tdesign:discount', + 'vi-tdesign:discount-filled', + 'vi-tdesign:dissatisfaction', + 'vi-tdesign:divide', + 'vi-tdesign:dividers', + 'vi-tdesign:dividers-1', + 'vi-tdesign:doge', + 'vi-tdesign:double-storey', + 'vi-tdesign:download', + 'vi-tdesign:download-1', + 'vi-tdesign:downscale', + 'vi-tdesign:drag-drop', + 'vi-tdesign:drag-move', + 'vi-tdesign:drink', + 'vi-tdesign:drumstick', + 'vi-tdesign:dv', + 'vi-tdesign:dvd', + 'vi-tdesign:earphone', + 'vi-tdesign:earth', + 'vi-tdesign:edit', + 'vi-tdesign:edit-1', + 'vi-tdesign:edit-2', + 'vi-tdesign:edit-off', + 'vi-tdesign:education', + 'vi-tdesign:eggplant', + 'vi-tdesign:ellipsis', + 'vi-tdesign:emo-emotional', + 'vi-tdesign:enter', + 'vi-tdesign:equal', + 'vi-tdesign:error', + 'vi-tdesign:error-circle', + 'vi-tdesign:error-circle-filled', + 'vi-tdesign:error-triangle', + 'vi-tdesign:excited', + 'vi-tdesign:excited-1', + 'vi-tdesign:expand-horizontal', + 'vi-tdesign:expand-vertical', + 'vi-tdesign:explore', + 'vi-tdesign:explore-off', + 'vi-tdesign:exposure', + 'vi-tdesign:extension', + 'vi-tdesign:extension-off', + 'vi-tdesign:face-retouching', + 'vi-tdesign:fact-check', + 'vi-tdesign:fahrenheit-scale', + 'vi-tdesign:feel-at-ease', + 'vi-tdesign:ferocious', + 'vi-tdesign:ferris-wheel', + 'vi-tdesign:file', + 'vi-tdesign:file-1', + 'vi-tdesign:file-add', + 'vi-tdesign:file-add-1', + 'vi-tdesign:file-attachment', + 'vi-tdesign:file-blocked', + 'vi-tdesign:file-code', + 'vi-tdesign:file-code-1', + 'vi-tdesign:file-copy', + 'vi-tdesign:file-download', + 'vi-tdesign:file-excel', + 'vi-tdesign:file-export', + 'vi-tdesign:file-icon', + 'vi-tdesign:file-image', + 'vi-tdesign:file-import', + 'vi-tdesign:file-locked', + 'vi-tdesign:file-minus', + 'vi-tdesign:file-music', + 'vi-tdesign:file-onenote', + 'vi-tdesign:file-outlook', + 'vi-tdesign:file-paste', + 'vi-tdesign:file-pdf', + 'vi-tdesign:file-powerpoint', + 'vi-tdesign:file-restore', + 'vi-tdesign:file-safety', + 'vi-tdesign:file-search', + 'vi-tdesign:file-setting', + 'vi-tdesign:file-teams', + 'vi-tdesign:file-unknown', + 'vi-tdesign:file-unlocked', + 'vi-tdesign:file-word', + 'vi-tdesign:file-zip', + 'vi-tdesign:fill-color', + 'vi-tdesign:fill-color-1', + 'vi-tdesign:film', + 'vi-tdesign:film-1', + 'vi-tdesign:filter', + 'vi-tdesign:filter-1', + 'vi-tdesign:filter-2', + 'vi-tdesign:filter-3', + 'vi-tdesign:filter-clear', + 'vi-tdesign:filter-off', + 'vi-tdesign:fingerprint', + 'vi-tdesign:fingerprint-1', + 'vi-tdesign:fingerprint-2', + 'vi-tdesign:fingerprint-3', + 'vi-tdesign:fish', + 'vi-tdesign:flag', + 'vi-tdesign:flag-1', + 'vi-tdesign:flag-2', + 'vi-tdesign:flag-3', + 'vi-tdesign:flag-4', + 'vi-tdesign:flashlight', + 'vi-tdesign:flight-landing', + 'vi-tdesign:flight-takeoff', + 'vi-tdesign:flip-smiling-face', + 'vi-tdesign:flip-to-back', + 'vi-tdesign:flip-to-front', + 'vi-tdesign:focus', + 'vi-tdesign:fog', + 'vi-tdesign:fog-night', + 'vi-tdesign:fog-sunny', + 'vi-tdesign:folder', + 'vi-tdesign:folder-1', + 'vi-tdesign:folder-add', + 'vi-tdesign:folder-add-1', + 'vi-tdesign:folder-blocked', + 'vi-tdesign:folder-details', + 'vi-tdesign:folder-export', + 'vi-tdesign:folder-import', + 'vi-tdesign:folder-locked', + 'vi-tdesign:folder-minus', + 'vi-tdesign:folder-move', + 'vi-tdesign:folder-off', + 'vi-tdesign:folder-open', + 'vi-tdesign:folder-open-1', + 'vi-tdesign:folder-search', + 'vi-tdesign:folder-setting', + 'vi-tdesign:folder-shared', + 'vi-tdesign:folder-unlocked', + 'vi-tdesign:folder-zip', + 'vi-tdesign:forest', + 'vi-tdesign:fork', + 'vi-tdesign:form', + 'vi-tdesign:format-horizontal-align-bottom', + 'vi-tdesign:format-horizontal-align-center', + 'vi-tdesign:format-horizontal-align-top', + 'vi-tdesign:format-vertical-align-center', + 'vi-tdesign:format-vertical-align-left', + 'vi-tdesign:format-vertical-align-right', + 'vi-tdesign:forward', + 'vi-tdesign:frame', + 'vi-tdesign:frame-1', + 'vi-tdesign:fries', + 'vi-tdesign:fullscreen', + 'vi-tdesign:fullscreen-1', + 'vi-tdesign:fullscreen-2', + 'vi-tdesign:fullscreen-exit', + 'vi-tdesign:fullscreen-exit-1', + 'vi-tdesign:function-curve', + 'vi-tdesign:functions', + 'vi-tdesign:functions-1', + 'vi-tdesign:gamepad', + 'vi-tdesign:gamepad-1', + 'vi-tdesign:gamma', + 'vi-tdesign:garlic', + 'vi-tdesign:gender-female', + 'vi-tdesign:gender-male', + 'vi-tdesign:gesture-applause', + 'vi-tdesign:gesture-click', + 'vi-tdesign:gesture-down', + 'vi-tdesign:gesture-expansion', + 'vi-tdesign:gesture-left', + 'vi-tdesign:gesture-left-slip', + 'vi-tdesign:gesture-pray', + 'vi-tdesign:gesture-pray-1', + 'vi-tdesign:gesture-press', + 'vi-tdesign:gesture-ranslation', + 'vi-tdesign:gesture-ranslation-1', + 'vi-tdesign:gesture-right', + 'vi-tdesign:gesture-right-slip', + 'vi-tdesign:gesture-slide-up', + 'vi-tdesign:gesture-up', + 'vi-tdesign:gesture-up-1', + 'vi-tdesign:gesture-up-2', + 'vi-tdesign:gesture-up-and-down', + 'vi-tdesign:gesture-wipe-down', + 'vi-tdesign:gift', + 'vi-tdesign:giggle', + 'vi-tdesign:git-branch', + 'vi-tdesign:git-commit', + 'vi-tdesign:git-merge', + 'vi-tdesign:git-pull-request', + 'vi-tdesign:git-repository', + 'vi-tdesign:git-repository-commits', + 'vi-tdesign:git-repository-private', + 'vi-tdesign:gps', + 'vi-tdesign:grape', + 'vi-tdesign:greater-than', + 'vi-tdesign:greater-than-or-equal', + 'vi-tdesign:green-onion', + 'vi-tdesign:grid-add', + 'vi-tdesign:grid-view', + 'vi-tdesign:guitar', + 'vi-tdesign:hamburger', + 'vi-tdesign:happy', + 'vi-tdesign:hard-disk-storage', + 'vi-tdesign:hard-drive', + 'vi-tdesign:hashtag', + 'vi-tdesign:hd', + 'vi-tdesign:heart', + 'vi-tdesign:heart-filled', + 'vi-tdesign:help', + 'vi-tdesign:help-circle', + 'vi-tdesign:help-circle-filled', + 'vi-tdesign:help-rectangle', + 'vi-tdesign:highlight', + 'vi-tdesign:highlight-1', + 'vi-tdesign:history', + 'vi-tdesign:history-setting', + 'vi-tdesign:home', + 'vi-tdesign:hospital', + 'vi-tdesign:hospital-1', + 'vi-tdesign:hotspot-wave', + 'vi-tdesign:hourglass', + 'vi-tdesign:houses', + 'vi-tdesign:houses-1', + 'vi-tdesign:houses-2', + 'vi-tdesign:html5', + 'vi-tdesign:https', + 'vi-tdesign:ice-cream', + 'vi-tdesign:icon', + 'vi-tdesign:image', + 'vi-tdesign:image-1', + 'vi-tdesign:image-add', + 'vi-tdesign:image-edit', + 'vi-tdesign:image-error', + 'vi-tdesign:image-off', + 'vi-tdesign:image-search', + 'vi-tdesign:indent-left', + 'vi-tdesign:indent-right', + 'vi-tdesign:indicator', + 'vi-tdesign:info-circle', + 'vi-tdesign:info-circle-filled', + 'vi-tdesign:ink', + 'vi-tdesign:install', + 'vi-tdesign:install-desktop', + 'vi-tdesign:install-mobile', + 'vi-tdesign:institution', + 'vi-tdesign:institution-checked', + 'vi-tdesign:internet', + 'vi-tdesign:ipod', + 'vi-tdesign:joyful', + 'vi-tdesign:jump', + 'vi-tdesign:jump-off', + 'vi-tdesign:keyboard', + 'vi-tdesign:laptop', + 'vi-tdesign:layers', + 'vi-tdesign:layout', + 'vi-tdesign:leaderboard', + 'vi-tdesign:lemon', + 'vi-tdesign:lemon-slice', + 'vi-tdesign:less-than', + 'vi-tdesign:less-than-or-equal', + 'vi-tdesign:letters-a', + 'vi-tdesign:letters-b', + 'vi-tdesign:letters-c', + 'vi-tdesign:letters-d', + 'vi-tdesign:letters-e', + 'vi-tdesign:letters-f', + 'vi-tdesign:letters-g', + 'vi-tdesign:letters-h', + 'vi-tdesign:letters-i', + 'vi-tdesign:letters-j', + 'vi-tdesign:letters-k', + 'vi-tdesign:letters-l', + 'vi-tdesign:letters-m', + 'vi-tdesign:letters-n', + 'vi-tdesign:letters-o', + 'vi-tdesign:letters-p', + 'vi-tdesign:letters-q', + 'vi-tdesign:letters-r', + 'vi-tdesign:letters-s', + 'vi-tdesign:letters-t', + 'vi-tdesign:letters-u', + 'vi-tdesign:letters-v', + 'vi-tdesign:letters-w', + 'vi-tdesign:letters-x', + 'vi-tdesign:letters-y', + 'vi-tdesign:letters-z', + 'vi-tdesign:lightbulb', + 'vi-tdesign:lightbulb-circle', + 'vi-tdesign:lighthouse', + 'vi-tdesign:lighthouse-1', + 'vi-tdesign:lighthouse-2', + 'vi-tdesign:lighting-circle', + 'vi-tdesign:line-height', + 'vi-tdesign:link', + 'vi-tdesign:link-1', + 'vi-tdesign:link-unlink', + 'vi-tdesign:liquor', + 'vi-tdesign:list', + 'vi-tdesign:load', + 'vi-tdesign:loading', + 'vi-tdesign:location', + 'vi-tdesign:location-1', + 'vi-tdesign:location-enlargement', + 'vi-tdesign:location-error', + 'vi-tdesign:location-parking-place', + 'vi-tdesign:location-reduction', + 'vi-tdesign:location-setting', + 'vi-tdesign:lock-off', + 'vi-tdesign:lock-on', + 'vi-tdesign:lock-time', + 'vi-tdesign:login', + 'vi-tdesign:logo-adobe-illustrate', + 'vi-tdesign:logo-adobe-photoshop', + 'vi-tdesign:logo-adobe-photoshop-1', + 'vi-tdesign:logo-android', + 'vi-tdesign:logo-apple', + 'vi-tdesign:logo-apple-filled', + 'vi-tdesign:logo-behance', + 'vi-tdesign:logo-chrome', + 'vi-tdesign:logo-chrome-filled', + 'vi-tdesign:logo-cinema4d', + 'vi-tdesign:logo-codepen', + 'vi-tdesign:logo-codesandbox', + 'vi-tdesign:logo-dribbble', + 'vi-tdesign:logo-facebook', + 'vi-tdesign:logo-figma', + 'vi-tdesign:logo-framer', + 'vi-tdesign:logo-github', + 'vi-tdesign:logo-github-filled', + 'vi-tdesign:logo-gitlab', + 'vi-tdesign:logo-ie', + 'vi-tdesign:logo-ie-filled', + 'vi-tdesign:logo-instagram', + 'vi-tdesign:logo-qq', + 'vi-tdesign:logo-twitter', + 'vi-tdesign:logo-wechat', + 'vi-tdesign:logo-wechat-stroke', + 'vi-tdesign:logo-wecom', + 'vi-tdesign:logo-windows', + 'vi-tdesign:logo-windows-filled', + 'vi-tdesign:logo-youtube', + 'vi-tdesign:logout', + 'vi-tdesign:look-around', + 'vi-tdesign:loudspeaker', + 'vi-tdesign:mail', + 'vi-tdesign:map', + 'vi-tdesign:map-3d', + 'vi-tdesign:map-add', + 'vi-tdesign:map-aiming', + 'vi-tdesign:map-blocked', + 'vi-tdesign:map-bubble', + 'vi-tdesign:map-cancel', + 'vi-tdesign:map-chat', + 'vi-tdesign:map-checked', + 'vi-tdesign:map-collection', + 'vi-tdesign:map-connection', + 'vi-tdesign:map-distance', + 'vi-tdesign:map-double', + 'vi-tdesign:map-edit', + 'vi-tdesign:map-grid', + 'vi-tdesign:map-information', + 'vi-tdesign:map-information-1', + 'vi-tdesign:map-information-2', + 'vi-tdesign:map-location', + 'vi-tdesign:map-locked', + 'vi-tdesign:map-marked', + 'vi-tdesign:map-navigation', + 'vi-tdesign:map-outline', + 'vi-tdesign:map-route-planning', + 'vi-tdesign:map-ruler', + 'vi-tdesign:map-safety', + 'vi-tdesign:map-search', + 'vi-tdesign:map-search-1', + 'vi-tdesign:map-setting', + 'vi-tdesign:map-unlocked', + 'vi-tdesign:mark-as-unread', + 'vi-tdesign:markup', + 'vi-tdesign:mathematics', + 'vi-tdesign:measurement', + 'vi-tdesign:measurement-1', + 'vi-tdesign:measurement-2', + 'vi-tdesign:meat-pepper', + 'vi-tdesign:media-library', + 'vi-tdesign:member', + 'vi-tdesign:menu', + 'vi-tdesign:menu-application', + 'vi-tdesign:menu-fold', + 'vi-tdesign:menu-unfold', + 'vi-tdesign:merge-cells', + 'vi-tdesign:microphone', + 'vi-tdesign:microphone-1', + 'vi-tdesign:microphone-2', + 'vi-tdesign:milk', + 'vi-tdesign:minus', + 'vi-tdesign:minus-circle', + 'vi-tdesign:minus-circle-filled', + 'vi-tdesign:minus-rectangle', + 'vi-tdesign:minus-rectangle-filled', + 'vi-tdesign:mirror', + 'vi-tdesign:mobile', + 'vi-tdesign:mobile-blocked', + 'vi-tdesign:mobile-list', + 'vi-tdesign:mobile-navigation', + 'vi-tdesign:mobile-shortcut', + 'vi-tdesign:mobile-vibrate', + 'vi-tdesign:mode-dark', + 'vi-tdesign:mode-light', + 'vi-tdesign:module', + 'vi-tdesign:money', + 'vi-tdesign:monument', + 'vi-tdesign:moon', + 'vi-tdesign:moon-fall', + 'vi-tdesign:moon-rising', + 'vi-tdesign:more', + 'vi-tdesign:mosque', + 'vi-tdesign:mosque-1', + 'vi-tdesign:mouse', + 'vi-tdesign:move', + 'vi-tdesign:move-1', + 'vi-tdesign:movie-clapper', + 'vi-tdesign:multiply', + 'vi-tdesign:museum', + 'vi-tdesign:museum-1', + 'vi-tdesign:museum-2', + 'vi-tdesign:mushroom', + 'vi-tdesign:mushroom-1', + 'vi-tdesign:music', + 'vi-tdesign:music-1', + 'vi-tdesign:music-2', + 'vi-tdesign:music-rectangle-add', + 'vi-tdesign:navigation-arrow', + 'vi-tdesign:next', + 'vi-tdesign:no-expression', + 'vi-tdesign:noodle', + 'vi-tdesign:notification', + 'vi-tdesign:notification-add', + 'vi-tdesign:notification-circle', + 'vi-tdesign:notification-error', + 'vi-tdesign:notification-filled', + 'vi-tdesign:numbers-0', + 'vi-tdesign:numbers-0-1', + 'vi-tdesign:numbers-1', + 'vi-tdesign:numbers-1-1', + 'vi-tdesign:numbers-2', + 'vi-tdesign:numbers-2-1', + 'vi-tdesign:numbers-3', + 'vi-tdesign:numbers-3-1', + 'vi-tdesign:numbers-4', + 'vi-tdesign:numbers-4-1', + 'vi-tdesign:numbers-5', + 'vi-tdesign:numbers-5-1', + 'vi-tdesign:numbers-6', + 'vi-tdesign:numbers-6-1', + 'vi-tdesign:numbers-7', + 'vi-tdesign:numbers-7-1', + 'vi-tdesign:numbers-8', + 'vi-tdesign:numbers-8-1', + 'vi-tdesign:numbers-9', + 'vi-tdesign:numbers-9-1', + 'vi-tdesign:nut', + 'vi-tdesign:object-storage', + 'vi-tdesign:open-mouth', + 'vi-tdesign:opera', + 'vi-tdesign:order-adjustment-column', + 'vi-tdesign:order-ascending', + 'vi-tdesign:order-descending', + 'vi-tdesign:outbox', + 'vi-tdesign:page-first', + 'vi-tdesign:page-head', + 'vi-tdesign:page-last', + 'vi-tdesign:palace', + 'vi-tdesign:palace-1', + 'vi-tdesign:palace-2', + 'vi-tdesign:palace-3', + 'vi-tdesign:palace-4', + 'vi-tdesign:palette', + 'vi-tdesign:palette-1', + 'vi-tdesign:panorama-horizontal', + 'vi-tdesign:panorama-vertical', + 'vi-tdesign:pantone', + 'vi-tdesign:parabola', + 'vi-tdesign:parentheses', + 'vi-tdesign:paste', + 'vi-tdesign:patio', + 'vi-tdesign:pause', + 'vi-tdesign:pause-circle', + 'vi-tdesign:pause-circle-filled', + 'vi-tdesign:pause-circle-stroke', + 'vi-tdesign:pea', + 'vi-tdesign:peach', + 'vi-tdesign:pear', + 'vi-tdesign:pearl-of-the-orient', + 'vi-tdesign:pen', + 'vi-tdesign:pen-ball', + 'vi-tdesign:pen-brush', + 'vi-tdesign:pen-mark', + 'vi-tdesign:pen-quill', + 'vi-tdesign:pending', + 'vi-tdesign:percent', + 'vi-tdesign:personal-information', + 'vi-tdesign:phone-locked', + 'vi-tdesign:phone-search', + 'vi-tdesign:pi', + 'vi-tdesign:piano', + 'vi-tdesign:pin', + 'vi-tdesign:pin-filled', + 'vi-tdesign:play', + 'vi-tdesign:play-circle', + 'vi-tdesign:play-circle-filled', + 'vi-tdesign:play-circle-stroke', + 'vi-tdesign:play-circle-stroke-add', + 'vi-tdesign:play-demo', + 'vi-tdesign:play-rectangle', + 'vi-tdesign:plus', + 'vi-tdesign:popsicle', + 'vi-tdesign:portrait', + 'vi-tdesign:pout', + 'vi-tdesign:poweroff', + 'vi-tdesign:precise-monitor', + 'vi-tdesign:previous', + 'vi-tdesign:print', + 'vi-tdesign:pumpkin', + 'vi-tdesign:pyramid', + 'vi-tdesign:pyramid-maya', + 'vi-tdesign:qrcode', + 'vi-tdesign:quadratic', + 'vi-tdesign:questionnaire', + 'vi-tdesign:queue', + 'vi-tdesign:radar', + 'vi-tdesign:radio-1', + 'vi-tdesign:radio-2', + 'vi-tdesign:radish', + 'vi-tdesign:rain-heavy', + 'vi-tdesign:rain-light', + 'vi-tdesign:rain-medium', + 'vi-tdesign:rainbow', + 'vi-tdesign:rectangle', + 'vi-tdesign:refresh', + 'vi-tdesign:relation', + 'vi-tdesign:relativity', + 'vi-tdesign:remote-wave', + 'vi-tdesign:remove', + 'vi-tdesign:replay', + 'vi-tdesign:rice', + 'vi-tdesign:rice-ball', + 'vi-tdesign:roast', + 'vi-tdesign:rocket', + 'vi-tdesign:rollback', + 'vi-tdesign:rollfront', + 'vi-tdesign:root-list', + 'vi-tdesign:rotate', + 'vi-tdesign:rotate-locked', + 'vi-tdesign:rotation', + 'vi-tdesign:round', + 'vi-tdesign:router-wave', + 'vi-tdesign:rss', + 'vi-tdesign:ruler', + 'vi-tdesign:sailing-hotel', + 'vi-tdesign:sandwich', + 'vi-tdesign:saturation', + 'vi-tdesign:sausage', + 'vi-tdesign:save', + 'vi-tdesign:saving-pot', + 'vi-tdesign:scan', + 'vi-tdesign:screen-4k', + 'vi-tdesign:screencast', + 'vi-tdesign:screenshot', + 'vi-tdesign:scroll-bar', + 'vi-tdesign:sd-card', + 'vi-tdesign:sd-card-1', + 'vi-tdesign:search', + 'vi-tdesign:search-error', + 'vi-tdesign:secured', + 'vi-tdesign:send', + 'vi-tdesign:send-cancel', + 'vi-tdesign:sensors', + 'vi-tdesign:sensors-1', + 'vi-tdesign:sensors-2', + 'vi-tdesign:sensors-off', + 'vi-tdesign:serenity', + 'vi-tdesign:server', + 'vi-tdesign:service', + 'vi-tdesign:setting', + 'vi-tdesign:setting-1', + 'vi-tdesign:share', + 'vi-tdesign:share-1', + 'vi-tdesign:sharpness', + 'vi-tdesign:shield-error', + 'vi-tdesign:shimen', + 'vi-tdesign:shop', + 'vi-tdesign:shop-1', + 'vi-tdesign:shop-2', + 'vi-tdesign:shop-3', + 'vi-tdesign:shop-4', + 'vi-tdesign:shop-5', + 'vi-tdesign:shrimp', + 'vi-tdesign:shrink-horizontal', + 'vi-tdesign:shrink-vertical', + 'vi-tdesign:shutter', + 'vi-tdesign:shutup', + 'vi-tdesign:sim-card', + 'vi-tdesign:sim-card-1', + 'vi-tdesign:sim-card-2', + 'vi-tdesign:sinister-smile', + 'vi-tdesign:sip', + 'vi-tdesign:slash', + 'vi-tdesign:sleep', + 'vi-tdesign:slice', + 'vi-tdesign:slideshow', + 'vi-tdesign:smile', + 'vi-tdesign:sneer', + 'vi-tdesign:snowflake', + 'vi-tdesign:sonic', + 'vi-tdesign:sound', + 'vi-tdesign:sound-down', + 'vi-tdesign:sound-high', + 'vi-tdesign:sound-low', + 'vi-tdesign:sound-mute', + 'vi-tdesign:sound-mute-1', + 'vi-tdesign:sound-up', + 'vi-tdesign:space', + 'vi-tdesign:speechless-1', + 'vi-tdesign:star', + 'vi-tdesign:star-filled', + 'vi-tdesign:statue-of-jesus', + 'vi-tdesign:sticky-note', + 'vi-tdesign:stop', + 'vi-tdesign:stop-circle', + 'vi-tdesign:stop-circle-filled', + 'vi-tdesign:stop-circle-stroke', + 'vi-tdesign:store', + 'vi-tdesign:street-road', + 'vi-tdesign:street-road-1', + 'vi-tdesign:subtitle', + 'vi-tdesign:subway-line', + 'vi-tdesign:sum', + 'vi-tdesign:sun-fall', + 'vi-tdesign:sun-rising', + 'vi-tdesign:sunny', + 'vi-tdesign:support', + 'vi-tdesign:surprised', + 'vi-tdesign:surprised-1', + 'vi-tdesign:swap', + 'vi-tdesign:swap-left', + 'vi-tdesign:swap-right', + 'vi-tdesign:swear-1', + 'vi-tdesign:swear-2', + 'vi-tdesign:system-2', + 'vi-tdesign:system-3', + 'vi-tdesign:system-application', + 'vi-tdesign:system-blocked', + 'vi-tdesign:system-code', + 'vi-tdesign:system-components', + 'vi-tdesign:system-coordinate', + 'vi-tdesign:system-device', + 'vi-tdesign:system-interface', + 'vi-tdesign:system-location', + 'vi-tdesign:system-locked', + 'vi-tdesign:system-log', + 'vi-tdesign:system-marked', + 'vi-tdesign:system-messages', + 'vi-tdesign:system-regulation', + 'vi-tdesign:system-search', + 'vi-tdesign:system-setting', + 'vi-tdesign:system-storage', + 'vi-tdesign:system-sum', + 'vi-tdesign:system-unlocked', + 'vi-tdesign:tab', + 'vi-tdesign:table', + 'vi-tdesign:table-1', + 'vi-tdesign:table-2', + 'vi-tdesign:table-add', + 'vi-tdesign:table-split', + 'vi-tdesign:tag', + 'vi-tdesign:tangerinr', + 'vi-tdesign:tape', + 'vi-tdesign:task', + 'vi-tdesign:task-1', + 'vi-tdesign:task-add', + 'vi-tdesign:task-add-1', + 'vi-tdesign:task-checked', + 'vi-tdesign:task-error', + 'vi-tdesign:task-location', + 'vi-tdesign:task-marked', + 'vi-tdesign:task-setting', + 'vi-tdesign:task-visible', + 'vi-tdesign:tea', + 'vi-tdesign:teahouse', + 'vi-tdesign:template', + 'vi-tdesign:temple', + 'vi-tdesign:terminal', + 'vi-tdesign:terminal-rectangle', + 'vi-tdesign:terminal-rectangle-1', + 'vi-tdesign:terminal-window', + 'vi-tdesign:textbox', + 'vi-tdesign:textformat-bold', + 'vi-tdesign:textformat-color', + 'vi-tdesign:textformat-italic', + 'vi-tdesign:textformat-strikethrough', + 'vi-tdesign:textformat-underline', + 'vi-tdesign:textformat-wrap', + 'vi-tdesign:theaters', + 'vi-tdesign:thumb-down', + 'vi-tdesign:thumb-down-1', + 'vi-tdesign:thumb-down-2', + 'vi-tdesign:thumb-up', + 'vi-tdesign:thumb-up-1', + 'vi-tdesign:thumb-up-2', + 'vi-tdesign:thunder', + 'vi-tdesign:thunderstorm', + 'vi-tdesign:thunderstorm-night', + 'vi-tdesign:thunderstorm-sunny', + 'vi-tdesign:ticket', + 'vi-tdesign:time', + 'vi-tdesign:time-filled', + 'vi-tdesign:tips', + 'vi-tdesign:tips-double', + 'vi-tdesign:tomato', + 'vi-tdesign:tools', + 'vi-tdesign:tools-circle', + 'vi-tdesign:tornado', + 'vi-tdesign:tower', + 'vi-tdesign:tower-1', + 'vi-tdesign:tower-2', + 'vi-tdesign:tower-3', + 'vi-tdesign:tower-clock', + 'vi-tdesign:town', + 'vi-tdesign:traffic', + 'vi-tdesign:traffic-events', + 'vi-tdesign:transform', + 'vi-tdesign:transform-1', + 'vi-tdesign:transform-2', + 'vi-tdesign:transform-3', + 'vi-tdesign:translate', + 'vi-tdesign:translate-1', + 'vi-tdesign:tree-list', + 'vi-tdesign:tree-round-dot', + 'vi-tdesign:tree-round-dot-vertical', + 'vi-tdesign:tree-square-dot', + 'vi-tdesign:tree-square-dot-vertical', + 'vi-tdesign:trending-down', + 'vi-tdesign:trending-up', + 'vi-tdesign:tv', + 'vi-tdesign:tv-1', + 'vi-tdesign:tv-2', + 'vi-tdesign:typography', + 'vi-tdesign:uncomfortable', + 'vi-tdesign:uncomfortable-1', + 'vi-tdesign:uncomfortable-2', + 'vi-tdesign:undertake', + 'vi-tdesign:undertake-delivery', + 'vi-tdesign:undertake-environment-protection', + 'vi-tdesign:undertake-hold-up', + 'vi-tdesign:undertake-transaction', + 'vi-tdesign:unfold-less', + 'vi-tdesign:unfold-more', + 'vi-tdesign:unhappy', + 'vi-tdesign:unhappy-1', + 'vi-tdesign:uninstall', + 'vi-tdesign:upload', + 'vi-tdesign:upload-1', + 'vi-tdesign:upscale', + 'vi-tdesign:usb', + 'vi-tdesign:user', + 'vi-tdesign:user-1', + 'vi-tdesign:user-add', + 'vi-tdesign:user-arrow-down', + 'vi-tdesign:user-arrow-left', + 'vi-tdesign:user-arrow-right', + 'vi-tdesign:user-arrow-up', + 'vi-tdesign:user-avatar', + 'vi-tdesign:user-blocked', + 'vi-tdesign:user-business', + 'vi-tdesign:user-checked', + 'vi-tdesign:user-checked-1', + 'vi-tdesign:user-circle', + 'vi-tdesign:user-clear', + 'vi-tdesign:user-error-1', + 'vi-tdesign:user-invisible', + 'vi-tdesign:user-list', + 'vi-tdesign:user-locked', + 'vi-tdesign:user-marked', + 'vi-tdesign:user-password', + 'vi-tdesign:user-safety', + 'vi-tdesign:user-search', + 'vi-tdesign:user-setting', + 'vi-tdesign:user-talk', + 'vi-tdesign:user-talk-1', + 'vi-tdesign:user-talk-off-1', + 'vi-tdesign:user-time', + 'vi-tdesign:user-transmit', + 'vi-tdesign:user-unknown', + 'vi-tdesign:user-unlocked', + 'vi-tdesign:user-vip', + 'vi-tdesign:user-visible', + 'vi-tdesign:usergroup', + 'vi-tdesign:usergroup-add', + 'vi-tdesign:usergroup-clear', + 'vi-tdesign:vehicle', + 'vi-tdesign:verified', + 'vi-tdesign:verify', + 'vi-tdesign:video', + 'vi-tdesign:video-camera', + 'vi-tdesign:video-camera-1', + 'vi-tdesign:video-camera-2', + 'vi-tdesign:video-camera-dollar', + 'vi-tdesign:video-camera-minus', + 'vi-tdesign:video-camera-music', + 'vi-tdesign:video-camera-off', + 'vi-tdesign:video-library', + 'vi-tdesign:view-agenda', + 'vi-tdesign:view-column', + 'vi-tdesign:view-in-ar', + 'vi-tdesign:view-list', + 'vi-tdesign:view-module', + 'vi-tdesign:visual-recognition', + 'vi-tdesign:wallet', + 'vi-tdesign:watch', + 'vi-tdesign:watermelon', + 'vi-tdesign:wave-left', + 'vi-tdesign:wave-right', + 'vi-tdesign:wealth', + 'vi-tdesign:wealth-1', + 'vi-tdesign:widget', + 'vi-tdesign:wifi', + 'vi-tdesign:wifi-1', + 'vi-tdesign:wifi-off', + 'vi-tdesign:wifi-off-1', + 'vi-tdesign:window', + 'vi-tdesign:window-1', + 'vi-tdesign:windy', + 'vi-tdesign:windy-rain', + 'vi-tdesign:wink', + 'vi-tdesign:work', + 'vi-tdesign:work-history', + 'vi-tdesign:work-off', + 'vi-tdesign:wry-smile', + 'vi-tdesign:zoom-in', + 'vi-tdesign:zoom-out' + ] +} diff --git a/src/components/ImageCropping/index.ts b/src/components/ImageCropping/index.ts new file mode 100644 index 000000000..d6c0f2592 --- /dev/null +++ b/src/components/ImageCropping/index.ts @@ -0,0 +1,3 @@ +import ImageCropping from './src/ImageCropping.vue' + +export { ImageCropping } diff --git a/src/components/ImageCropping/src/ImageCropping.vue b/src/components/ImageCropping/src/ImageCropping.vue new file mode 100644 index 000000000..2f8c6852e --- /dev/null +++ b/src/components/ImageCropping/src/ImageCropping.vue @@ -0,0 +1,259 @@ + + + diff --git a/src/components/ImageViewer/index.ts b/src/components/ImageViewer/index.ts new file mode 100644 index 000000000..35764d6b0 --- /dev/null +++ b/src/components/ImageViewer/index.ts @@ -0,0 +1,33 @@ +import ImageViewer from './src/ImageViewer.vue' +import { isClient } from '@/utils/is' +import { createVNode, render, VNode } from 'vue' +import { ImageViewerProps } from './src/types' + +let instance: Nullable = null + +export function createImageViewer(options: ImageViewerProps) { + if (!isClient) return + const { + urlList, + initialIndex = 0, + infinite = true, + hideOnClickModal = false, + teleported = false, + zIndex = 2000, + show = true + } = options + + const propsData: Partial = {} + const container = document.createElement('div') + propsData.urlList = urlList + propsData.initialIndex = initialIndex + propsData.infinite = infinite + propsData.hideOnClickModal = hideOnClickModal + propsData.teleported = teleported + propsData.zIndex = zIndex + propsData.show = show + + document.body.appendChild(container) + instance = createVNode(ImageViewer, propsData) + render(instance, container) +} diff --git a/src/components/ImageViewer/src/ImageViewer.vue b/src/components/ImageViewer/src/ImageViewer.vue new file mode 100644 index 000000000..b9afe176b --- /dev/null +++ b/src/components/ImageViewer/src/ImageViewer.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/ImageViewer/src/types/index.ts b/src/components/ImageViewer/src/types/index.ts new file mode 100644 index 000000000..2fff4c0ad --- /dev/null +++ b/src/components/ImageViewer/src/types/index.ts @@ -0,0 +1,9 @@ +export interface ImageViewerProps { + urlList?: string[] + zIndex?: number + initialIndex?: number + infinite?: boolean + hideOnClickModal?: boolean + teleported?: boolean + show?: boolean +} diff --git a/src/components/Infotip/index.ts b/src/components/Infotip/index.ts new file mode 100644 index 000000000..eb99944dc --- /dev/null +++ b/src/components/Infotip/index.ts @@ -0,0 +1,5 @@ +import Infotip from './src/Infotip.vue' + +export type { InfoTipSchema } from './src/types' + +export { Infotip } diff --git a/src/components/Infotip/src/Infotip.vue b/src/components/Infotip/src/Infotip.vue new file mode 100644 index 000000000..ff9136c5a --- /dev/null +++ b/src/components/Infotip/src/Infotip.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/Infotip/src/types/index.ts b/src/components/Infotip/src/types/index.ts new file mode 100644 index 000000000..50398db0c --- /dev/null +++ b/src/components/Infotip/src/types/index.ts @@ -0,0 +1,4 @@ +export interface InfoTipSchema { + label: string + keys?: string[] +} diff --git a/src/components/InputPassword/index.ts b/src/components/InputPassword/index.ts new file mode 100644 index 000000000..1dcc38e9a --- /dev/null +++ b/src/components/InputPassword/index.ts @@ -0,0 +1,3 @@ +import InputPassword from './src/InputPassword.vue' + +export { InputPassword } diff --git a/src/components/InputPassword/src/InputPassword.vue b/src/components/InputPassword/src/InputPassword.vue new file mode 100644 index 000000000..d9aa928c0 --- /dev/null +++ b/src/components/InputPassword/src/InputPassword.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/components/JsonEditor/index.ts b/src/components/JsonEditor/index.ts new file mode 100644 index 000000000..53a2d067f --- /dev/null +++ b/src/components/JsonEditor/index.ts @@ -0,0 +1,4 @@ +import JsonEditor from './src/JsonEditor.vue' +export type { JsonEditorProps } from './src/types' + +export { JsonEditor } diff --git a/src/components/JsonEditor/src/JsonEditor.vue b/src/components/JsonEditor/src/JsonEditor.vue new file mode 100644 index 000000000..a1c0a43fe --- /dev/null +++ b/src/components/JsonEditor/src/JsonEditor.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/components/JsonEditor/src/types/index.ts b/src/components/JsonEditor/src/types/index.ts new file mode 100644 index 000000000..d77097f78 --- /dev/null +++ b/src/components/JsonEditor/src/types/index.ts @@ -0,0 +1,23 @@ +export interface JsonEditorProps { + value: any + deep?: number + showLength?: boolean + showLineNumbers?: boolean + showLineNumber?: boolean + showIcon?: boolean + showDoubleQuotes?: boolean + virtual?: boolean + height?: number + itemHeight?: number + rootPath?: string + nodeSelectable?: (...args: any[]) => boolean + selectableType?: 'multiple' | 'single' + showSelectController?: boolean + selectOnClickNode?: boolean + highlightSelectedNode?: boolean + collapsedOnClickBrackets?: boolean + renderNodeKey?: (...args: any[]) => any + renderNodeValue?: (...args: any[]) => any + editable?: boolean + editableTrigger?: 'click' | 'dblclick' +} diff --git a/src/components/LocaleDropdown/index.ts b/src/components/LocaleDropdown/index.ts new file mode 100644 index 000000000..4d9b98a39 --- /dev/null +++ b/src/components/LocaleDropdown/index.ts @@ -0,0 +1,5 @@ +import LocaleDropdown from './src/LocaleDropdown.vue' + +export type { Language, LocaleDropdownType } from './src/types' + +export { LocaleDropdown } diff --git a/src/components/LocaleDropdown/src/LocaleDropdown.vue b/src/components/LocaleDropdown/src/LocaleDropdown.vue new file mode 100644 index 000000000..e1a03422d --- /dev/null +++ b/src/components/LocaleDropdown/src/LocaleDropdown.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/components/LocaleDropdown/src/types/index.ts b/src/components/LocaleDropdown/src/types/index.ts new file mode 100644 index 000000000..c749dce72 --- /dev/null +++ b/src/components/LocaleDropdown/src/types/index.ts @@ -0,0 +1,10 @@ +export interface Language { + el: Recordable + name: string +} + +export interface LocaleDropdownType { + lang: LocaleType + name?: string + elLocale?: Language +} diff --git a/src/components/Logo/index.ts b/src/components/Logo/index.ts new file mode 100644 index 000000000..1c4224c99 --- /dev/null +++ b/src/components/Logo/index.ts @@ -0,0 +1,3 @@ +import Logo from './src/Logo.vue' + +export { Logo } diff --git a/src/components/Logo/src/Logo.vue b/src/components/Logo/src/Logo.vue new file mode 100644 index 000000000..89cbe905f --- /dev/null +++ b/src/components/Logo/src/Logo.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/components/Menu/index.ts b/src/components/Menu/index.ts new file mode 100644 index 000000000..a6ec6965b --- /dev/null +++ b/src/components/Menu/index.ts @@ -0,0 +1,3 @@ +import Menu from './src/Menu.vue' + +export { Menu } diff --git a/src/components/Menu/src/Menu.vue b/src/components/Menu/src/Menu.vue new file mode 100644 index 000000000..083d03c8e --- /dev/null +++ b/src/components/Menu/src/Menu.vue @@ -0,0 +1,278 @@ + + + + + diff --git a/src/components/Menu/src/components/useRenderMenuItem.tsx b/src/components/Menu/src/components/useRenderMenuItem.tsx new file mode 100644 index 000000000..96914cc2f --- /dev/null +++ b/src/components/Menu/src/components/useRenderMenuItem.tsx @@ -0,0 +1,59 @@ +import { ElSubMenu, ElMenuItem } from 'element-plus' +import { unref } from 'vue' +import { hasOneShowingChild } from '../helper' +import { isUrl } from '@/utils/is' +import { useRenderMenuTitle } from './useRenderMenuTitle' +import { pathResolve } from '@/utils/routerHelper' +import { useDesign } from '@/hooks/web/useDesign' + +const { getPrefixCls } = useDesign() +const prefixCls = getPrefixCls('submenu') + +const { renderMenuTitle } = useRenderMenuTitle() + +export const useRenderMenuItem = (menuMode) => + // allRouters: AppRouteRecordRaw[] = [], + { + const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => { + return routers + .filter((v) => !v.meta?.hidden) + .map((v) => { + const meta = v.meta ?? {} + const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v) + const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath(allRouters, v.path).join('/') + + if ( + oneShowingChild && + (!onlyOneChild?.children || onlyOneChild?.noShowingChildren) && + !meta?.alwaysShow + ) { + return ( + + {{ + default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta) + }} + + ) + } else { + return ( + + {{ + title: () => renderMenuTitle(meta), + default: () => renderMenuItem(v.children!, fullPath) + }} + + ) + } + }) + } + + return { + renderMenuItem + } + } diff --git a/src/components/Menu/src/components/useRenderMenuTitle.tsx b/src/components/Menu/src/components/useRenderMenuTitle.tsx new file mode 100644 index 000000000..8941d9d76 --- /dev/null +++ b/src/components/Menu/src/components/useRenderMenuTitle.tsx @@ -0,0 +1,27 @@ +import type { RouteMeta } from 'vue-router' +import { Icon } from '@/components/Icon' +import { useI18n } from '@/hooks/web/useI18n' + +export const useRenderMenuTitle = () => { + const renderMenuTitle = (meta: RouteMeta) => { + const { t } = useI18n() + const { title = 'Please set title', icon } = meta + + return icon ? ( + <> + + + {t(title as string)} + + + ) : ( + + {t(title as string)} + + ) + } + + return { + renderMenuTitle + } +} diff --git a/src/components/Menu/src/helper.ts b/src/components/Menu/src/helper.ts new file mode 100644 index 000000000..003cf1050 --- /dev/null +++ b/src/components/Menu/src/helper.ts @@ -0,0 +1,54 @@ +import { ref, unref } from 'vue' +import { findPath } from '@/utils/tree' + +type OnlyOneChildType = AppRouteRecordRaw & { noShowingChildren?: boolean } + +interface HasOneShowingChild { + oneShowingChild?: boolean + onlyOneChild?: OnlyOneChildType +} + +export const getAllParentPath = (treeData: T[], path: string) => { + const menuList = findPath(treeData, (n) => n.path === path) as AppRouteRecordRaw[] + return (menuList || []).map((item) => item.path) +} + +export const hasOneShowingChild = ( + children: AppRouteRecordRaw[] = [], + parent: AppRouteRecordRaw +): HasOneShowingChild => { + const onlyOneChild = ref() + + const showingChildren = children.filter((v) => { + const meta = v.meta ?? {} + if (meta.hidden) { + return false + } else { + // Temp set(will be used if only has one showing child) + onlyOneChild.value = v + return true + } + }) + + // When there is only one child router, the child router is displayed by default + if (showingChildren.length === 1) { + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + // Show parent if there are no child router to display + if (!showingChildren.length) { + onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + return { + oneShowingChild: false, + onlyOneChild: unref(onlyOneChild) + } +} diff --git a/src/components/Permission/index.ts b/src/components/Permission/index.ts new file mode 100644 index 000000000..250ae75b8 --- /dev/null +++ b/src/components/Permission/index.ts @@ -0,0 +1,4 @@ +import Permission from './src/Permission.vue' +import { hasPermi } from './src/utils' + +export { Permission, hasPermi } diff --git a/src/components/Permission/src/Permission.vue b/src/components/Permission/src/Permission.vue new file mode 100644 index 000000000..8581a9ddf --- /dev/null +++ b/src/components/Permission/src/Permission.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/Permission/src/utils.ts b/src/components/Permission/src/utils.ts new file mode 100644 index 000000000..4c0a9b5f8 --- /dev/null +++ b/src/components/Permission/src/utils.ts @@ -0,0 +1,14 @@ +import { useI18n } from '@/hooks/web/useI18n' +import router from '@/router' + +export const hasPermi = (value: string) => { + const { t } = useI18n() + const permission = (router.currentRoute.value.meta.permission || []) as string[] + if (!value) { + throw new Error(t('permission.hasPermission')) + } + if (permission.includes(value)) { + return true + } + return false +} diff --git a/src/components/Qrcode/index.ts b/src/components/Qrcode/index.ts new file mode 100644 index 000000000..263f039de --- /dev/null +++ b/src/components/Qrcode/index.ts @@ -0,0 +1,5 @@ +import Qrcode from './src/Qrcode.vue' + +export type { QrcodeLogo } from './src/types' + +export { Qrcode } diff --git a/src/components/Qrcode/src/Qrcode.vue b/src/components/Qrcode/src/Qrcode.vue new file mode 100644 index 000000000..3b3cc1c5b --- /dev/null +++ b/src/components/Qrcode/src/Qrcode.vue @@ -0,0 +1,252 @@ + + + + + diff --git a/src/components/Qrcode/src/types/index.ts b/src/components/Qrcode/src/types/index.ts new file mode 100644 index 000000000..86cdf0b96 --- /dev/null +++ b/src/components/Qrcode/src/types/index.ts @@ -0,0 +1,9 @@ +export interface QrcodeLogo { + src?: string + logoSize?: number + bgColor?: string + borderSize?: number + crossOrigin?: string + borderRadius?: number + logoRadius?: number +} diff --git a/src/components/Screenfull/index.ts b/src/components/Screenfull/index.ts new file mode 100644 index 000000000..faec2d8ed --- /dev/null +++ b/src/components/Screenfull/index.ts @@ -0,0 +1,3 @@ +import Screenfull from './src/Screenfull.vue' + +export { Screenfull } diff --git a/src/components/Screenfull/src/Screenfull.vue b/src/components/Screenfull/src/Screenfull.vue new file mode 100644 index 000000000..048df9a3c --- /dev/null +++ b/src/components/Screenfull/src/Screenfull.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts new file mode 100644 index 000000000..696ad8419 --- /dev/null +++ b/src/components/Search/index.ts @@ -0,0 +1,15 @@ +import { FormSchema, FormSetProps } from '../Form' +import Search from './src/Search.vue' + +export type { SearchProps } from './src/types' + +export interface SearchExpose { + setValues: (data: Recordable) => void + setProps: (props: Recordable) => void + delSchema: (field: string) => void + addSchema: (formSchema: FormSchema, index?: number) => void + setSchema: (schemaProps: FormSetProps[]) => void + getFormData: () => Promise +} + +export { Search } diff --git a/src/components/Search/src/Search.vue b/src/components/Search/src/Search.vue new file mode 100644 index 000000000..3e57ed6f8 --- /dev/null +++ b/src/components/Search/src/Search.vue @@ -0,0 +1,271 @@ + + + diff --git a/src/components/Search/src/components/ActionButton.vue b/src/components/Search/src/components/ActionButton.vue new file mode 100644 index 000000000..8de183875 --- /dev/null +++ b/src/components/Search/src/components/ActionButton.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/components/Search/src/types/index.ts b/src/components/Search/src/types/index.ts new file mode 100644 index 000000000..7a1901da7 --- /dev/null +++ b/src/components/Search/src/types/index.ts @@ -0,0 +1,16 @@ +import { FormSchema } from '@/components/Form' + +export interface SearchProps { + schema?: FormSchema[] + isCol?: boolean + labelWidth?: string | number + layout?: 'inline' | 'bottom' + buttonPosition?: 'left' | 'right' | 'center' + showSearch?: boolean + showReset?: boolean + showExpand?: boolean + expandField?: string + inline?: boolean + removeNoValueItem?: boolean + model?: Recordable +} diff --git a/src/components/Setting/index.ts b/src/components/Setting/index.ts new file mode 100644 index 000000000..b64c9add8 --- /dev/null +++ b/src/components/Setting/index.ts @@ -0,0 +1,3 @@ +import Setting from './src/Setting.vue' + +export { Setting } diff --git a/src/components/Setting/src/Setting.vue b/src/components/Setting/src/Setting.vue new file mode 100644 index 000000000..083c5dffb --- /dev/null +++ b/src/components/Setting/src/Setting.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/src/components/Setting/src/components/ColorRadioPicker.vue b/src/components/Setting/src/components/ColorRadioPicker.vue new file mode 100644 index 000000000..977417667 --- /dev/null +++ b/src/components/Setting/src/components/ColorRadioPicker.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/Setting/src/components/InterfaceDisplay.vue b/src/components/Setting/src/components/InterfaceDisplay.vue new file mode 100644 index 000000000..466dc651e --- /dev/null +++ b/src/components/Setting/src/components/InterfaceDisplay.vue @@ -0,0 +1,227 @@ + + + diff --git a/src/components/Setting/src/components/LayoutRadioPicker.vue b/src/components/Setting/src/components/LayoutRadioPicker.vue new file mode 100644 index 000000000..2b6d4b569 --- /dev/null +++ b/src/components/Setting/src/components/LayoutRadioPicker.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/components/SizeDropdown/index.ts b/src/components/SizeDropdown/index.ts new file mode 100644 index 000000000..516488d63 --- /dev/null +++ b/src/components/SizeDropdown/index.ts @@ -0,0 +1,3 @@ +import SizeDropdown from './src/SizeDropdown.vue' + +export { SizeDropdown } diff --git a/src/components/SizeDropdown/src/SizeDropdown.vue b/src/components/SizeDropdown/src/SizeDropdown.vue new file mode 100644 index 000000000..eb5591785 --- /dev/null +++ b/src/components/SizeDropdown/src/SizeDropdown.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/components/TabMenu/index.ts b/src/components/TabMenu/index.ts new file mode 100644 index 000000000..b5fd71cdd --- /dev/null +++ b/src/components/TabMenu/index.ts @@ -0,0 +1,3 @@ +import TabMenu from './src/TabMenu.vue' + +export { TabMenu } diff --git a/src/components/TabMenu/src/TabMenu.vue b/src/components/TabMenu/src/TabMenu.vue new file mode 100644 index 000000000..e6cf366c0 --- /dev/null +++ b/src/components/TabMenu/src/TabMenu.vue @@ -0,0 +1,251 @@ + + + diff --git a/src/components/TabMenu/src/helper.ts b/src/components/TabMenu/src/helper.ts new file mode 100644 index 000000000..cb4696ea3 --- /dev/null +++ b/src/components/TabMenu/src/helper.ts @@ -0,0 +1,51 @@ +import { getAllParentPath } from '@/components/Menu/src/helper' +import { isUrl } from '@/utils/is' +import { cloneDeep } from 'lodash-es' +import { reactive } from 'vue' + +export type TabMapTypes = { + [key: string]: string[] +} + +export const tabPathMap = reactive({}) + +export const initTabMap = (routes: AppRouteRecordRaw[]) => { + for (const v of routes) { + const meta = v.meta ?? {} + if (!meta?.hidden) { + tabPathMap[v.path] = [] + } + } +} + +export const filterMenusPath = ( + routes: AppRouteRecordRaw[], + allRoutes: AppRouteRecordRaw[] +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + for (const v of routes) { + let data: Nullable = null + const meta = v.meta ?? {} + if (!meta.hidden || meta.canTo) { + const allParentPath = getAllParentPath(allRoutes, v.path) + + const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/') + + data = cloneDeep(v) + data.path = fullPath + if (v.children && data) { + data.children = filterMenusPath(v.children, allRoutes) + } + + if (data) { + res.push(data) + } + + if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) { + tabPathMap[allParentPath[0]].push(fullPath) + } + } + } + + return res +} diff --git a/src/components/Table/index.ts b/src/components/Table/index.ts new file mode 100644 index 000000000..472ae5dc0 --- /dev/null +++ b/src/components/Table/index.ts @@ -0,0 +1,21 @@ +import Table from './src/Table.vue' +import { ElTable } from 'element-plus' +import { TableColumn, TableSetProps } from './src/types' + +export type { + TableColumn, + TableSlotDefault, + Pagination, + TableSetProps, + TableProps +} from './src/types' + +export interface TableExpose { + setProps: (props: Recordable) => void + setColumn: (columnProps: TableSetProps[]) => void + addColumn: (column: TableColumn, index?: number) => void + delColumn: (field: string) => void + elTableRef: ComponentRef +} + +export { Table } diff --git a/src/components/Table/src/Table.vue b/src/components/Table/src/Table.vue new file mode 100644 index 000000000..9d496f033 --- /dev/null +++ b/src/components/Table/src/Table.vue @@ -0,0 +1,587 @@ + diff --git a/src/components/Table/src/components/ColumnSetting.vue b/src/components/Table/src/components/ColumnSetting.vue new file mode 100644 index 000000000..35595f96b --- /dev/null +++ b/src/components/Table/src/components/ColumnSetting.vue @@ -0,0 +1,166 @@ + + + diff --git a/src/components/Table/src/components/TableActions.vue b/src/components/Table/src/components/TableActions.vue new file mode 100644 index 000000000..05336bbed --- /dev/null +++ b/src/components/Table/src/components/TableActions.vue @@ -0,0 +1,105 @@ + diff --git a/src/components/Table/src/helper/index.ts b/src/components/Table/src/helper/index.ts new file mode 100644 index 000000000..d8b34a8a7 --- /dev/null +++ b/src/components/Table/src/helper/index.ts @@ -0,0 +1,8 @@ +export const setIndex = (reserveIndex: boolean, index: number, size: number, current: number) => { + const newIndex = index + 1 + if (reserveIndex) { + return size * (current - 1) + newIndex + } else { + return newIndex + } +} diff --git a/src/components/Table/src/types/index.ts b/src/components/Table/src/types/index.ts new file mode 100644 index 000000000..21200a747 --- /dev/null +++ b/src/components/Table/src/types/index.ts @@ -0,0 +1,98 @@ +import { TableProps as ElTableProps } from 'element-plus' +export interface TableColumn { + field: string + label?: string + type?: string + /** + * 是否隐藏 + */ + hidden?: boolean + children?: TableColumn[] + slots?: { + default?: (...args: any[]) => JSX.Element | JSX.Element[] | null + header?: (...args: any[]) => JSX.Element | null + } + index?: number | ((index: number) => number) + columnKey?: string + width?: string | number + minWidth?: string | number + fixed?: boolean | 'left' | 'right' + renderHeader?: (...args: any[]) => JSX.Element | null + // sortable?: boolean + sortMethod?: (...args: any[]) => number + sortBy?: string | string[] | ((...args: any[]) => string | string[]) + sortOrders?: (string | null)[] + resizable?: boolean + formatter?: (...args: any[]) => any + showOverflowTooltip?: boolean + align?: 'left' | 'center' | 'right' + headerAlign?: 'left' | 'center' | 'right' + className?: string + labelClassName?: string + selectable?: (...args: any[]) => boolean + reserveSelection?: boolean + filters?: Array<{ text: string; value: string }> + filterPlacement?: string + filterMultiple?: boolean + filterMethod?: (...args: any[]) => boolean + filteredValue?: string[] + [key: string]: any +} + +export interface TableSlotDefault { + row: Recordable + column: TableColumn + $index: number + [key: string]: any +} + +export interface Pagination { + small?: boolean + background?: boolean + pageSize?: number + defaultPageSize?: number + total?: number + pageCount?: number + pagerCount?: number + currentPage?: number + defaultCurrentPage?: number + layout?: string + pageSizes?: number[] + popperClass?: string + prevText?: string + nextText?: string + disabled?: boolean + hideOnSinglePage?: boolean +} + +export interface TableSetProps { + field: string + path: string + value: any +} + +export interface TableProps extends Omit>, 'data'> { + pageSize?: number + currentPage?: number + showAction?: boolean + // 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip, + showOverflowTooltip?: boolean + // 表头 + columns?: TableColumn[] + // 是否展示分页 + pagination?: Pagination | undefined + // 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key) + reserveSelection?: boolean + // 加载状态 + loading?: boolean + // 是否叠加索引 + reserveIndex?: boolean + // 对齐方式 + align?: 'left' | 'center' | 'right' + // 表头对齐方式 + headerAlign?: 'left' | 'center' | 'right' + imagePreview?: string[] + videoPreview?: string[] + sortable?: boolean + data?: Recordable +} diff --git a/src/components/TagsView/index.ts b/src/components/TagsView/index.ts new file mode 100644 index 000000000..30e604a8f --- /dev/null +++ b/src/components/TagsView/index.ts @@ -0,0 +1,3 @@ +import TagsView from './src/TagsView.vue' + +export { TagsView } diff --git a/src/components/TagsView/src/TagsView.vue b/src/components/TagsView/src/TagsView.vue new file mode 100644 index 000000000..da3336bea --- /dev/null +++ b/src/components/TagsView/src/TagsView.vue @@ -0,0 +1,590 @@ + + + + + diff --git a/src/components/TagsView/src/helper.ts b/src/components/TagsView/src/helper.ts new file mode 100644 index 000000000..912eb8eed --- /dev/null +++ b/src/components/TagsView/src/helper.ts @@ -0,0 +1,21 @@ +import type { RouteLocationNormalizedLoaded } from 'vue-router' +import { pathResolve } from '@/utils/routerHelper' + +export const filterAffixTags = (routes: AppRouteRecordRaw[], parentPath = '') => { + let tags: RouteLocationNormalizedLoaded[] = [] + routes.forEach((route) => { + const meta = route.meta ?? {} + const tagPath = pathResolve(parentPath, route.path) + if (meta?.affix) { + tags.push({ ...route, path: tagPath, fullPath: tagPath } as RouteLocationNormalizedLoaded) + } + if (route.children) { + const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath) + if (tempTags.length >= 1) { + tags = [...tags, ...tempTags] + } + } + }) + + return tags +} diff --git a/src/components/ThemeSwitch/index.ts b/src/components/ThemeSwitch/index.ts new file mode 100644 index 000000000..823a27651 --- /dev/null +++ b/src/components/ThemeSwitch/index.ts @@ -0,0 +1,3 @@ +import ThemeSwitch from './src/ThemeSwitch.vue' + +export { ThemeSwitch } diff --git a/src/components/ThemeSwitch/src/ThemeSwitch.vue b/src/components/ThemeSwitch/src/ThemeSwitch.vue new file mode 100644 index 000000000..007105e2b --- /dev/null +++ b/src/components/ThemeSwitch/src/ThemeSwitch.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/components/UserInfo/index.ts b/src/components/UserInfo/index.ts new file mode 100644 index 000000000..c3a34aba4 --- /dev/null +++ b/src/components/UserInfo/index.ts @@ -0,0 +1,3 @@ +import UserInfo from './src/UserInfo.vue' + +export { UserInfo } diff --git a/src/components/UserInfo/src/UserInfo.vue b/src/components/UserInfo/src/UserInfo.vue new file mode 100644 index 000000000..526b0a03f --- /dev/null +++ b/src/components/UserInfo/src/UserInfo.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/components/UserInfo/src/components/LockDialog.vue b/src/components/UserInfo/src/components/LockDialog.vue new file mode 100644 index 000000000..886144538 --- /dev/null +++ b/src/components/UserInfo/src/components/LockDialog.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/components/UserInfo/src/components/LockPage.vue b/src/components/UserInfo/src/components/LockPage.vue new file mode 100644 index 000000000..1e5c9ef47 --- /dev/null +++ b/src/components/UserInfo/src/components/LockPage.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/src/components/Verify/SimpleVerify.vue b/src/components/Verify/SimpleVerify.vue new file mode 100644 index 000000000..08c4f994e --- /dev/null +++ b/src/components/Verify/SimpleVerify.vue @@ -0,0 +1,723 @@ + + + + + \ No newline at end of file diff --git a/src/components/Verify/index.ts b/src/components/Verify/index.ts new file mode 100644 index 000000000..9f269b505 --- /dev/null +++ b/src/components/Verify/index.ts @@ -0,0 +1,3 @@ +import Verify from './index.vue' + +export { Verify } \ No newline at end of file diff --git a/src/components/Verify/index.vue b/src/components/Verify/index.vue new file mode 100644 index 000000000..13af8a063 --- /dev/null +++ b/src/components/Verify/index.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/Verify/src/Verify.vue b/src/components/Verify/src/Verify.vue new file mode 100644 index 000000000..d8c061573 --- /dev/null +++ b/src/components/Verify/src/Verify.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/src/components/Verify/src/Verify/VerifyPoints.vue b/src/components/Verify/src/Verify/VerifyPoints.vue new file mode 100644 index 000000000..0bad3c627 --- /dev/null +++ b/src/components/Verify/src/Verify/VerifyPoints.vue @@ -0,0 +1,239 @@ + + + + + \ No newline at end of file diff --git a/src/components/Verify/src/Verify/VerifySlide.vue b/src/components/Verify/src/Verify/VerifySlide.vue new file mode 100644 index 000000000..85cab6eea --- /dev/null +++ b/src/components/Verify/src/Verify/VerifySlide.vue @@ -0,0 +1,418 @@ + + + + + \ No newline at end of file diff --git a/src/components/Verify/src/Verify/index.js b/src/components/Verify/src/Verify/index.js new file mode 100644 index 000000000..96e6f70f1 --- /dev/null +++ b/src/components/Verify/src/Verify/index.js @@ -0,0 +1,4 @@ +import VerifySlide from './VerifySlide.vue' +import VerifyPoints from './VerifyPoints.vue' + +export { VerifySlide, VerifyPoints } \ No newline at end of file diff --git a/src/components/VideoPlayer/index.ts b/src/components/VideoPlayer/index.ts new file mode 100644 index 000000000..247decad5 --- /dev/null +++ b/src/components/VideoPlayer/index.ts @@ -0,0 +1,27 @@ +import { VNode, createVNode, render } from 'vue' +import VideoPlayer from './src/VideoPlayer.vue' +import { isClient } from '@/utils/is' +import { VideoPlayerViewer } from '@/components/VideoPlayerViewer' +import { toAnyString } from '@/utils' + +export { VideoPlayer } + +let instance: Nullable = null + +export function createVideoViewer(options: { url: string; poster?: string; show?: boolean }) { + if (!isClient) return + const { url, poster } = options + + const propsData: Partial<{ url: string; poster?: string; show?: boolean; id?: string }> = {} + const container = document.createElement('div') + const id = toAnyString() + container.id = id + propsData.url = url + propsData.poster = poster + propsData.show = true + propsData.id = id + + document.body.appendChild(container) + instance = createVNode(VideoPlayerViewer, propsData) + render(instance, container) +} diff --git a/src/components/VideoPlayer/src/VideoPlayer.vue b/src/components/VideoPlayer/src/VideoPlayer.vue new file mode 100644 index 000000000..83c8d30ba --- /dev/null +++ b/src/components/VideoPlayer/src/VideoPlayer.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/components/VideoPlayerViewer/index.ts b/src/components/VideoPlayerViewer/index.ts new file mode 100644 index 000000000..7f9915519 --- /dev/null +++ b/src/components/VideoPlayerViewer/index.ts @@ -0,0 +1,3 @@ +import VideoPlayerViewer from './src/VideoPlayerViewer.vue' + +export { VideoPlayerViewer } diff --git a/src/components/VideoPlayerViewer/src/VideoPlayerViewer.vue b/src/components/VideoPlayerViewer/src/VideoPlayerViewer.vue new file mode 100644 index 000000000..56968dfef --- /dev/null +++ b/src/components/VideoPlayerViewer/src/VideoPlayerViewer.vue @@ -0,0 +1,49 @@ + + diff --git a/src/components/Waterfall/index.ts b/src/components/Waterfall/index.ts new file mode 100644 index 000000000..6fed67f1d --- /dev/null +++ b/src/components/Waterfall/index.ts @@ -0,0 +1,3 @@ +import Waterfall from './src/Waterfall.vue' + +export { Waterfall } diff --git a/src/components/Waterfall/src/Waterfall.vue b/src/components/Waterfall/src/Waterfall.vue new file mode 100644 index 000000000..32a0aa73c --- /dev/null +++ b/src/components/Waterfall/src/Waterfall.vue @@ -0,0 +1,234 @@ + + + diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 000000000..782d073fd --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,14 @@ +import type { App } from 'vue' +import { Icon } from './Icon' +import { Permission } from './Permission' +import { BaseButton } from './Button' +import { Verify } from './Verify' + +export const setupGlobCom = (app: App): void => { + app.component('Icon', Icon) + app.component('Permission', Permission) + app.component('BaseButton', BaseButton) + app.component('Verify', Verify) +} + +export * from './Verify' diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 000000000..c6f628138 --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1,39 @@ +/** + * 请求成功状态码 + */ +export const SUCCESS_CODE = 0 + +/** + * 请求contentType + */ +export const CONTENT_TYPE: AxiosContentType = 'application/json' + +/** + * 请求超时时间 + */ +export const REQUEST_TIMEOUT = 60000 + +/** + * 不重定向白名单 + */ +export const NO_REDIRECT_WHITE_LIST = ['/login'] + +/** + * 不重置路由白名单 + */ +export const NO_RESET_WHITE_LIST = ['Redirect', 'Login', 'NoFind', 'Root'] + +/** + * 表格默认过滤列设置字段 + */ +export const DEFAULT_FILTER_COLUMN = ['expand', 'selection'] + +/** + * 是否根据headers->content-type自动转换数据格式 + */ +export const TRANSFORM_REQUEST_DATA = true + +/** + * 全局图标前缀 + */ +export const ICON_PREFIX = 'vi-' diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 000000000..11b1da85d --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,10 @@ +import type { App } from 'vue' +import { setupPermissionDirective } from './permission/hasPermi' + +/** + * 导出指令:v-xxx + * @methods hasPermi 按钮权限,用法: v-hasPermi + */ +export const setupPermission = (app: App) => { + setupPermissionDirective(app) +} diff --git a/src/directives/permission/hasPermi.ts b/src/directives/permission/hasPermi.ts new file mode 100644 index 000000000..0a74d9496 --- /dev/null +++ b/src/directives/permission/hasPermi.ts @@ -0,0 +1,37 @@ +import type { App, Directive, DirectiveBinding } from 'vue' +import { useI18n } from '@/hooks/web/useI18n' +import router from '@/router' + +const { t } = useI18n() + +const hasPermission = (value: string): boolean => { + const permission = (router.currentRoute.value.meta.permission || []) as string[] + if (!value) { + throw new Error(t('permission.hasPermission')) + } + if (permission.includes(value)) { + return true + } + return false +} +function hasPermi(el: Element, binding: DirectiveBinding) { + const value = binding.value + + const flag = hasPermission(value) + if (!flag) { + el.parentNode?.removeChild(el) + } +} +const mounted = (el: Element, binding: DirectiveBinding) => { + hasPermi(el, binding) +} + +const permiDirective: Directive = { + mounted +} + +export const setupPermissionDirective = (app: App) => { + app.directive('hasPermi', permiDirective) +} + +export default permiDirective diff --git a/src/hooks/event/useEventBus.ts b/src/hooks/event/useEventBus.ts new file mode 100644 index 000000000..d9ee8325b --- /dev/null +++ b/src/hooks/event/useEventBus.ts @@ -0,0 +1,26 @@ +import mitt from 'mitt' +import { onBeforeUnmount } from 'vue' + +interface Option { + name: string // 事件名称 + callback: Fn // 回调 +} + +const emitter = mitt() + +export const useEventBus = (option?: Option) => { + if (option) { + emitter.on(option.name, option.callback) + + onBeforeUnmount(() => { + emitter.off(option.name) + }) + } + + return { + on: emitter.on, + off: emitter.off, + emit: emitter.emit, + all: emitter.all + } +} diff --git a/src/hooks/event/useScrollTo.ts b/src/hooks/event/useScrollTo.ts new file mode 100644 index 000000000..74fd673c8 --- /dev/null +++ b/src/hooks/event/useScrollTo.ts @@ -0,0 +1,62 @@ +import { ref, unref } from 'vue' + +export interface ScrollToParams { + el: HTMLElement + to: number + position: string + duration?: number + callback?: () => void +} + +const easeInOutQuad = (t: number, b: number, c: number, d: number) => { + t /= d / 2 + if (t < 1) { + return (c / 2) * t * t + b + } + t-- + return (-c / 2) * (t * (t - 2) - 1) + b +} +const move = (el: HTMLElement, position: string, amount: number) => { + el[position] = amount +} + +export function useScrollTo({ + el, + position = 'scrollLeft', + to, + duration = 500, + callback +}: ScrollToParams) { + const isActiveRef = ref(false) + const start = el[position] + const change = to - start + const increment = 20 + let currentTime = 0 + + function animateScroll() { + if (!unref(isActiveRef)) { + return + } + currentTime += increment + const val = easeInOutQuad(currentTime, start, change, duration) + move(el, position, val) + if (currentTime < duration && unref(isActiveRef)) { + requestAnimationFrame(animateScroll) + } else { + if (callback) { + callback() + } + } + } + + function run() { + isActiveRef.value = true + animateScroll() + } + + function stop() { + isActiveRef.value = false + } + + return { start: run, stop } +} diff --git a/src/hooks/useCache.ts b/src/hooks/useCache.ts new file mode 100644 index 000000000..4f39f307f --- /dev/null +++ b/src/hooks/useCache.ts @@ -0,0 +1,39 @@ +/** + * 配置浏览器本地存储的方式,可直接存储对象数组。 + */ + +import WebStorageCache from 'web-storage-cache' + +type CacheType = 'localStorage' | 'sessionStorage' + +export const CACHE_KEY = { + // 用户相关 + ROLE_ROUTERS: 'roleRouters', + USER: 'user', + // 系统设置 + IS_DARK: 'isDark', + LANG: 'lang', + THEME: 'theme', + LAYOUT: 'layout', + DICT_CACHE: 'dictCache', + // 登录表单 + LoginForm: 'loginForm', + TenantId: 'tenantId' +} + +export const useCache = (type: CacheType = 'localStorage') => { + const wsCache: WebStorageCache = new WebStorageCache({ + storage: type + }) + + return { + wsCache + } +} + +export const deleteUserCache = () => { + const { wsCache } = useCache() + wsCache.delete(CACHE_KEY.USER) + wsCache.delete(CACHE_KEY.ROLE_ROUTERS) + // 注意,不要清理 LoginForm 登录表单 +} diff --git a/src/hooks/web/useClipboard.ts b/src/hooks/web/useClipboard.ts new file mode 100644 index 000000000..fb8c3d61d --- /dev/null +++ b/src/hooks/web/useClipboard.ts @@ -0,0 +1,47 @@ +import { ref } from 'vue' + +const useClipboard = () => { + const copied = ref(false) + const text = ref('') + const isSupported = ref(false) + + if (!navigator.clipboard && !document.execCommand) { + isSupported.value = false + } else { + isSupported.value = true + } + + const copy = (str: string) => { + if (navigator.clipboard) { + navigator.clipboard.writeText(str).then(() => { + text.value = str + copied.value = true + resetCopied() + }) + return + } + const input = document.createElement('input') + input.setAttribute('readonly', 'readonly') + input.setAttribute('value', str) + document.body.appendChild(input) + input.select() + input.setSelectionRange(0, 9999) + if (document.execCommand('copy')) { + text.value = str + document.execCommand('copy') + copied.value = true + resetCopied() + } + document.body.removeChild(input) + } + + const resetCopied = () => { + setTimeout(() => { + copied.value = false + }, 1500) + } + + return { copy, text, copied, isSupported } +} + +export { useClipboard } diff --git a/src/hooks/web/useConfigGlobal.ts b/src/hooks/web/useConfigGlobal.ts new file mode 100644 index 000000000..d1e490b23 --- /dev/null +++ b/src/hooks/web/useConfigGlobal.ts @@ -0,0 +1,10 @@ +import { ConfigGlobalTypes } from '@/components/ConfigGlobal' +import { inject } from 'vue' + +export const useConfigGlobal = () => { + const configGlobal = inject('configGlobal', {}) as ConfigGlobalTypes + + return { + configGlobal + } +} diff --git a/src/hooks/web/useCrudSchemas.ts b/src/hooks/web/useCrudSchemas.ts new file mode 100644 index 000000000..5e61d653d --- /dev/null +++ b/src/hooks/web/useCrudSchemas.ts @@ -0,0 +1,163 @@ +import { reactive } from 'vue' +import { eachTree, treeMap, filter } from '@/utils/tree' +import { FormSchema } from '@/components/Form' +import { TableColumn } from '@/components/Table' +import { DescriptionsSchema } from '@/components/Descriptions' + +export type CrudSchema = Omit & { + search?: CrudSearchParams + table?: CrudTableParams + form?: CrudFormParams + detail?: CrudDescriptionsParams + children?: CrudSchema[] +} + +interface CrudSearchParams extends Omit { + // 是否隐藏在查询项 + hidden?: boolean +} + +interface CrudTableParams extends Omit { + // 是否隐藏表头 + hidden?: boolean +} + +interface CrudFormParams extends Omit { + // 是否隐藏表单项 + hidden?: boolean +} + +interface CrudDescriptionsParams extends Omit { + // 是否隐藏表单项 + hidden?: boolean +} + +interface AllSchemas { + searchSchema: FormSchema[] + tableColumns: TableColumn[] + formSchema: FormSchema[] + detailSchema: DescriptionsSchema[] +} + +/** + * @deprecated 不推荐使用,感觉过于繁琐,不是很灵活 可能会在某个版本中删除 + */ +export const useCrudSchemas = ( + crudSchema: CrudSchema[] +): { + allSchemas: AllSchemas +} => { + // 所有结构数据 + const allSchemas = reactive({ + searchSchema: [], + tableColumns: [], + formSchema: [], + detailSchema: [] + }) + + const searchSchema = filterSearchSchema(crudSchema) + // @ts-ignore + allSchemas.searchSchema = searchSchema || [] + + const tableColumns = filterTableSchema(crudSchema) + allSchemas.tableColumns = tableColumns || [] + + const formSchema = filterFormSchema(crudSchema) + allSchemas.formSchema = formSchema + + const detailSchema = filterDescriptionsSchema(crudSchema) + allSchemas.detailSchema = detailSchema + + return { + allSchemas + } +} + +// 过滤 Search 结构 +const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => { + const searchSchema: FormSchema[] = [] + const length = crudSchema.length + + for (let i = 0; i < length; i++) { + const schemaItem = crudSchema[i] + if (schemaItem.search?.hidden === true) { + continue + } + // 判断是否隐藏 + const searchSchemaItem = { + component: schemaItem?.search?.component || 'Input', + ...schemaItem.search, + field: schemaItem.field, + label: schemaItem.search?.label || schemaItem.label + } + + searchSchema.push(searchSchemaItem) + } + + return searchSchema +} + +// 过滤 table 结构 +const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => { + const tableColumns = treeMap(crudSchema, { + conversion: (schema: CrudSchema) => { + if (!schema?.table?.hidden) { + return { + ...schema, + ...schema.table + } + } + } + }) + + // 第一次过滤会有 undefined 所以需要二次过滤 + return filter(tableColumns as TableColumn[], (data) => { + if (data.children === void 0) { + delete data.children + } + return !!data.field + }) +} + +// 过滤 form 结构 +const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => { + const formSchema: FormSchema[] = [] + const length = crudSchema.length + + for (let i = 0; i < length; i++) { + const formItem = crudSchema[i] + const formSchemaItem = { + component: formItem?.form?.component || 'Input', + ...formItem.form, + field: formItem.field, + label: formItem.form?.label || formItem.label + } + + formSchema.push(formSchemaItem) + } + + return formSchema +} + +// 过滤 descriptions 结构 +const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => { + const descriptionsSchema: FormSchema[] = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否隐藏 + if (!schemaItem?.detail?.hidden) { + const descriptionsSchemaItem = { + ...schemaItem.detail, + field: schemaItem.field, + label: schemaItem.detail?.label || schemaItem.label + } + + // 删除不必要的字段 + delete descriptionsSchemaItem.hidden + + descriptionsSchema.push(descriptionsSchemaItem) + } + }) + + return descriptionsSchema +} diff --git a/src/hooks/web/useDesign.ts b/src/hooks/web/useDesign.ts new file mode 100644 index 000000000..1ec349f84 --- /dev/null +++ b/src/hooks/web/useDesign.ts @@ -0,0 +1,18 @@ +import variables from '@/styles/variables.module.less' + +export const useDesign = () => { + const lessVariables = variables + + /** + * @param scope 类名 + * @returns 返回空间名-类名 + */ + const getPrefixCls = (scope: string) => { + return `${lessVariables.namespace}-${scope}` + } + + return { + variables: lessVariables, + getPrefixCls + } +} diff --git a/src/hooks/web/useForm.ts b/src/hooks/web/useForm.ts new file mode 100644 index 000000000..cdf5eace8 --- /dev/null +++ b/src/hooks/web/useForm.ts @@ -0,0 +1,149 @@ +import type { Form, FormExpose } from '@/components/Form' +import type { ElForm, ElFormItem } from 'element-plus' +import { ref, unref, nextTick } from 'vue' +import { FormSchema, FormSetProps, FormProps } from '@/components/Form' +import { isEmptyVal, isObject } from '@/utils/is' + +export const useForm = () => { + // From实例 + const formRef = ref() + + // ElForm实例 + const elFormRef = ref>() + + /** + * @param ref Form实例 + * @param elRef ElForm实例 + */ + const register = (ref: typeof Form & FormExpose, elRef: ComponentRef) => { + formRef.value = ref + elFormRef.value = elRef + } + + const getForm = async () => { + await nextTick() + const form = unref(formRef) + if (!form) { + console.error('The form is not registered. Please use the register method to register') + } + return form + } + + // 一些内置的方法 + const methods = { + /** + * @description 设置form组件的props + * @param props form组件的props + */ + setProps: async (props: FormProps = {}) => { + const form = await getForm() + form?.setProps(props) + if (props.model) { + form?.setValues(props.model) + } + }, + + /** + * @description 设置form的值 + * @param data 需要设置的数据 + */ + setValues: async (data: Recordable) => { + const form = await getForm() + form?.setValues(data) + }, + + /** + * @description 设置schema + * @param schemaProps 需要设置的schemaProps + */ + setSchema: async (schemaProps: FormSetProps[]) => { + const form = await getForm() + form?.setSchema(schemaProps) + }, + + /** + * @description 新增schema + * @param formSchema 需要新增数据 + * @param index 在哪里新增 + */ + addSchema: async (formSchema: FormSchema, index?: number) => { + const form = await getForm() + form?.addSchema(formSchema, index) + }, + + /** + * @description 删除schema + * @param field 删除哪个数据 + */ + delSchema: async (field: string) => { + const form = await getForm() + form?.delSchema(field) + }, + + /** + * @description 获取表单数据 + * @returns form data + */ + getFormData: async (filterEmptyVal = true): Promise => { + const form = await getForm() + const model = form?.formModel as any + if (filterEmptyVal) { + // 使用reduce过滤空值,并返回一个新对象 + return Object.keys(model).reduce((prev, next) => { + const value = model[next] + if (!isEmptyVal(value)) { + if (isObject(value)) { + if (Object.keys(value).length > 0) { + prev[next] = value + } + } else { + prev[next] = value + } + } + return prev + }, {}) as T + } else { + return model as T + } + }, + + /** + * @description 获取表单组件的实例 + * @param field 表单项唯一标识 + * @returns component instance + */ + getComponentExpose: async (field: string) => { + const form = await getForm() + return form?.getComponentExpose(field) + }, + + /** + * @description 获取formItem组件的实例 + * @param field 表单项唯一标识 + * @returns formItem instance + */ + getFormItemExpose: async (field: string) => { + const form = await getForm() + return form?.getFormItemExpose(field) as ComponentRef + }, + + /** + * @description 获取ElForm组件的实例 + * @returns ElForm instance + */ + getElFormExpose: async () => { + await getForm() + return unref(elFormRef) + }, + + getFormExpose: async () => { + await getForm() + return unref(formRef) + } + } + + return { + formRegister: register, + formMethods: methods + } +} diff --git a/src/hooks/web/useGuide.ts b/src/hooks/web/useGuide.ts new file mode 100644 index 000000000..7fd2fb090 --- /dev/null +++ b/src/hooks/web/useGuide.ts @@ -0,0 +1,49 @@ +import { Config, driver } from 'driver.js' +import 'driver.js/dist/driver.css' +import { useDesign } from '@/hooks/web/useDesign' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +const { variables } = useDesign() + +export const useGuide = (options?: Config) => { + const driverObj = driver( + options || { + showProgress: true, + nextBtnText: t('common.nextLabel'), + prevBtnText: t('common.prevLabel'), + doneBtnText: t('common.doneLabel'), + steps: [ + { + element: `#${variables.namespace}-menu`, + popover: { + title: t('common.menu'), + description: t('common.menuDes'), + side: 'right' + } + }, + { + element: `#${variables.namespace}-tool-header`, + popover: { + title: t('common.tool'), + description: t('common.toolDes'), + side: 'left' + } + }, + { + element: `#${variables.namespace}-tags-view`, + popover: { + title: t('common.tagsView'), + description: t('common.tagsViewDes'), + side: 'bottom' + } + } + ] + } + ) + + return { + ...driverObj + } +} diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts new file mode 100644 index 000000000..f1e0e7bd5 --- /dev/null +++ b/src/hooks/web/useI18n.ts @@ -0,0 +1,52 @@ +import { i18n } from '@/plugins/vueI18n' + +type I18nGlobalTranslation = { + (key: string): string + (key: string, locale: string): string + (key: string, locale: string, list: unknown[]): string + (key: string, locale: string, named: Record): string + (key: string, list: unknown[]): string + (key: string, named: Record): string +} + +type I18nTranslationRestParameters = [string, any] + +const getKey = (namespace: string | undefined, key: string) => { + if (!namespace) { + return key + } + if (key.startsWith(namespace)) { + return key + } + return `${namespace}.${key}` +} + +export const useI18n = ( + namespace?: string +): { + t: I18nGlobalTranslation +} => { + const normalFn = { + t: (key: string) => { + return getKey(namespace, key) + } + } + + if (!i18n) { + return normalFn + } + + const { t, ...methods } = i18n.global + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) return '' + if (!key.includes('.') && !namespace) return key + return (t as any)(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) + } + return { + ...methods, + t: tFn + } +} + +export const t = (key: string) => key diff --git a/src/hooks/web/useIcon.ts b/src/hooks/web/useIcon.ts new file mode 100644 index 000000000..b76bb2922 --- /dev/null +++ b/src/hooks/web/useIcon.ts @@ -0,0 +1,7 @@ +import { h } from 'vue' +import type { VNode } from 'vue' +import { Icon, IconTypes } from '@/components/Icon' + +export const useIcon = (props: IconTypes): VNode => { + return h(Icon, props) +} diff --git a/src/hooks/web/useLocale.ts b/src/hooks/web/useLocale.ts new file mode 100644 index 000000000..c65070ef3 --- /dev/null +++ b/src/hooks/web/useLocale.ts @@ -0,0 +1,35 @@ +import { i18n } from '@/plugins/vueI18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import { setHtmlPageLang } from '@/plugins/vueI18n/helper' + +const setI18nLanguage = (locale: LocaleType) => { + const localeStore = useLocaleStoreWithOut() + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale + } else { + ;(i18n.global.locale as any).value = locale + } + localeStore.setCurrentLocale({ + lang: locale + }) + setHtmlPageLang(locale) +} + +export const useLocale = () => { + // Switching the language will change the locale of useI18n + // And submit to configuration modification + const changeLocale = async (locale: LocaleType) => { + const globalI18n = i18n.global + + const langModule = await import(`../../locales/${locale}.ts`) + + globalI18n.setLocaleMessage(locale, langModule.default) + + setI18nLanguage(locale) + } + + return { + changeLocale + } +} diff --git a/src/hooks/web/useMessage.ts b/src/hooks/web/useMessage.ts new file mode 100644 index 000000000..ac2b552e0 --- /dev/null +++ b/src/hooks/web/useMessage.ts @@ -0,0 +1,95 @@ +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' +import { useI18n } from './useI18n' +export const useMessage = () => { + const { t } = useI18n() + return { + // 消息提示 + info(content: string) { + ElMessage.info(content) + }, + // 错误消息 + error(content: string) { + ElMessage.error(content) + }, + // 成功消息 + success(content: string) { + ElMessage.success(content) + }, + // 警告消息 + warning(content: string) { + ElMessage.warning(content) + }, + // 弹出提示 + alert(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle')) + }, + // 错误提示 + alertError(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'error' }) + }, + // 成功提示 + alertSuccess(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'success' }) + }, + // 警告提示 + alertWarning(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'warning' }) + }, + // 通知提示 + notify(content: string) { + ElNotification.info(content) + }, + // 错误通知 + notifyError(content: string) { + ElNotification.error(content) + }, + // 成功通知 + notifySuccess(content: string) { + ElNotification.success(content) + }, + // 警告通知 + notifyWarning(content: string) { + ElNotification.warning(content) + }, + // 确认窗体 + confirm(content: string, tip?: string) { + return ElMessageBox.confirm(content, tip ? tip : t('common.confirmTitle'), { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + }, + // 删除窗体 + delConfirm(content?: string, tip?: string) { + return ElMessageBox.confirm( + content ? content : t('common.delMessage'), + tip ? tip : t('common.confirmTitle'), + { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + } + ) + }, + // 导出窗体 + exportConfirm(content?: string, tip?: string) { + return ElMessageBox.confirm( + content ? content : t('common.exportMessage'), + tip ? tip : t('common.confirmTitle'), + { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + } + ) + }, + // 提交内容 + prompt(content: string, tip: string) { + return ElMessageBox.prompt(content, tip, { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + } + } +} diff --git a/src/hooks/web/useMonacoEditor.ts b/src/hooks/web/useMonacoEditor.ts new file mode 100644 index 000000000..ab464ea63 --- /dev/null +++ b/src/hooks/web/useMonacoEditor.ts @@ -0,0 +1,129 @@ +import * as monaco from 'monaco-editor' +import { ref, nextTick, onBeforeUnmount } from 'vue' +import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' +import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' +import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker' +import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker' +import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker' + +self.MonacoEnvironment = { + getWorker(_, label) { + if (label === 'json') { + return new jsonWorker() + } + if (label === 'css' || label === 'scss' || label === 'less') { + return new cssWorker() + } + if (label === 'html' || label === 'handlebars' || label === 'razor') { + return new htmlWorker() + } + if (label === 'typescript' || label === 'javascript') { + return new tsWorker() + } + return new editorWorker() + } +} + +export function useMonacoEditor(language: string = 'javascript') { + // 编辑器示例 + let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null + // 目标元素 + const monacoEditorRef = ref() + + // 创建实例 + function createEditor(editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}) { + if (!monacoEditorRef.value) return + monacoEditor = monaco.editor.create(monacoEditorRef.value, { + // 初始模型 + model: monaco.editor.createModel('', language), + // 是否启用预览图 + minimap: { enabled: true }, + // 圆角 + roundedSelection: true, + // 主题 + theme: 'vs-dark', + // 主键 + multiCursorModifier: 'ctrlCmd', + // 滚动条 + scrollbar: { + verticalScrollbarSize: 8, + horizontalScrollbarSize: 8 + }, + // 行号 + lineNumbers: 'on', + // tab大小 + tabSize: 2, + //字体大小 + fontSize: 14, + // 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进 + autoIndent: 'advanced', + // 自动布局 + automaticLayout: true, + ...editorOption + }) + return monacoEditor + } + + // 格式化 + async function formatDoc() { + await monacoEditor?.getAction('editor.action.formatDocument')?.run() + } + + // 数据更新 + function updateVal(val: string) { + nextTick(() => { + if (getOption(monaco.editor.EditorOption.readOnly)) { + updateOptions({ readOnly: false }) + } + monacoEditor?.setValue(val) + setTimeout(async () => { + await formatDoc() + }, 10) + }) + } + + // 配置更新 + function updateOptions(opt: monaco.editor.IStandaloneEditorConstructionOptions) { + monacoEditor?.updateOptions(opt) + } + + // 获取配置 + function getOption(name: monaco.editor.EditorOption) { + return monacoEditor?.getOption(name) + } + + // 获取实例 + function getEditor() { + return monacoEditor + } + + function changeLanguage(newLanguage: string) { + const model = monacoEditor?.getModel() + if (model) { + monaco.editor.setModelLanguage(model, newLanguage) + } + } + + function changeTheme(newTheme: string) { + monaco.editor.setTheme(newTheme) + } + + // 页面离开 销毁 + onBeforeUnmount(() => { + if (monacoEditor) { + monacoEditor.dispose() + } + }) + + return { + monacoEditorRef, + createEditor, + getEditor, + updateVal, + updateOptions, + getOption, + formatDoc, + changeLanguage, + changeTheme + } +} diff --git a/src/hooks/web/useNProgress.ts b/src/hooks/web/useNProgress.ts new file mode 100644 index 000000000..28990e7de --- /dev/null +++ b/src/hooks/web/useNProgress.ts @@ -0,0 +1,34 @@ +import { nextTick, unref } from 'vue' +import type { NProgressOptions } from 'nprogress' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { useCssVar } from '@vueuse/core' + +const primaryColor = useCssVar('--el-color-primary', document.documentElement) + +export const useNProgress = () => { + NProgress.configure({ showSpinner: false } as NProgressOptions) + + const initColor = async () => { + await nextTick() + const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef + if (bar) { + bar.style.background = unref(primaryColor.value) + } + } + + initColor() + + const start = () => { + NProgress.start() + } + + const done = () => { + NProgress.done() + } + + return { + start, + done + } +} diff --git a/src/hooks/web/useNetwork.ts b/src/hooks/web/useNetwork.ts new file mode 100644 index 000000000..66fa44642 --- /dev/null +++ b/src/hooks/web/useNetwork.ts @@ -0,0 +1,21 @@ +import { ref, onBeforeUnmount } from 'vue' + +const useNetwork = () => { + const online = ref(true) + + const updateNetwork = () => { + online.value = navigator.onLine + } + + window.addEventListener('online', updateNetwork) + window.addEventListener('offline', updateNetwork) + + onBeforeUnmount(() => { + window.removeEventListener('online', updateNetwork) + window.removeEventListener('offline', updateNetwork) + }) + + return { online } +} + +export { useNetwork } diff --git a/src/hooks/web/useNow.ts b/src/hooks/web/useNow.ts new file mode 100644 index 000000000..09d3176b2 --- /dev/null +++ b/src/hooks/web/useNow.ts @@ -0,0 +1,60 @@ +import { dateUtil } from '@/utils/dateUtil' +import { reactive, toRefs } from 'vue' +import { tryOnMounted, tryOnUnmounted } from '@vueuse/core' + +export const useNow = (immediate = true) => { + let timer: IntervalHandle + + const state = reactive({ + year: 0, + month: 0, + week: '', + day: 0, + hour: '', + minute: '', + second: 0, + meridiem: '' + }) + + const update = () => { + const now = dateUtil() + + const h = now.format('HH') + const m = now.format('mm') + const s = now.get('s') + + state.year = now.get('y') + state.month = now.get('M') + 1 + state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()] + state.day = now.get('date') + state.hour = h + state.minute = m + state.second = s + + state.meridiem = now.format('A') + } + + function start() { + update() + clearInterval(timer) + timer = setInterval(() => update(), 1000) + } + + function stop() { + clearInterval(timer) + } + + tryOnMounted(() => { + immediate && start() + }) + + tryOnUnmounted(() => { + stop() + }) + + return { + ...toRefs(state), + start, + stop + } +} diff --git a/src/hooks/web/usePageLoading.ts b/src/hooks/web/usePageLoading.ts new file mode 100644 index 000000000..995c94163 --- /dev/null +++ b/src/hooks/web/usePageLoading.ts @@ -0,0 +1,20 @@ +import { useAppStoreWithOut } from '@/store/modules/app' + +export const usePageLoading = () => { + const loadStart = () => { + const appStore = useAppStoreWithOut() + + appStore.setPageLoading(true) + } + + const loadDone = () => { + const appStore = useAppStoreWithOut() + + appStore.setPageLoading(false) + } + + return { + loadStart, + loadDone + } +} diff --git a/src/hooks/web/useSearch.ts b/src/hooks/web/useSearch.ts new file mode 100644 index 000000000..788c49f38 --- /dev/null +++ b/src/hooks/web/useSearch.ts @@ -0,0 +1,91 @@ +import { ref, unref, nextTick } from 'vue' +import { FormSchema, FormSetProps } from '@/components/Form' +import { SearchExpose, SearchProps } from '@/components/Search' + +export const useSearch = () => { + // Search实例 + const searchRef = ref() + + /** + * @param ref Search实例 + * @param elRef ElForm实例 + */ + const register = (ref: SearchExpose) => { + searchRef.value = ref + } + + const getSearch = async () => { + await nextTick() + const search = unref(searchRef) + if (!search) { + console.error('The Search is not registered. Please use the register method to register') + } + return search + } + + // 一些内置的方法 + const methods = { + /** + * @description 设置search组件的props + * @param field FormItem的field + */ + setProps: async (props: SearchProps = {}) => { + const search = await getSearch() + search?.setProps(props) + if (props.model) { + search?.setValues(props.model) + } + }, + + /** + * @description 设置form的值 + * @param data 需要设置的数据 + */ + setValues: async (data: Recordable) => { + const search = await getSearch() + search?.setValues(data) + }, + + /** + * @description 设置schema + * @param schemaProps 需要设置的schemaProps + */ + setSchema: async (schemaProps: FormSetProps[]) => { + const search = await getSearch() + search?.setSchema(schemaProps) + }, + + /** + * @description 新增schema + * @param formSchema 需要新增数据 + * @param index 在哪里新增 + */ + addSchema: async (formSchema: FormSchema, index?: number) => { + const search = await getSearch() + search?.addSchema(formSchema, index) + }, + + /** + * @description 删除schema + * @param field 删除哪个数据 + */ + delSchema: async (field: string) => { + const search = await getSearch() + search?.delSchema(field) + }, + + /** + * @description 获取表单数据 + * @returns form data + */ + getFormData: async (): Promise => { + const search = await getSearch() + return search?.getFormData() as T + } + } + + return { + searchRegister: register, + searchMethods: methods + } +} diff --git a/src/hooks/web/useStorage.ts b/src/hooks/web/useStorage.ts new file mode 100644 index 000000000..e33a6a567 --- /dev/null +++ b/src/hooks/web/useStorage.ts @@ -0,0 +1,46 @@ +// 获取传入的值的类型 +const getValueType = (value: any) => { + const type = Object.prototype.toString.call(value) + return type.slice(8, -1) +} + +export const useStorage = (type: 'sessionStorage' | 'localStorage' = 'sessionStorage') => { + const setStorage = (key: string, value: any) => { + const valueType = getValueType(value) + window[type].setItem(key, JSON.stringify({ type: valueType, value })) + } + + const getStorage = (key: string) => { + const value = window[type].getItem(key) + if (value) { + const { value: val } = JSON.parse(value) + return val + } else { + return value + } + } + + const removeStorage = (key: string) => { + window[type].removeItem(key) + } + + const clear = (excludes?: string[]) => { + // 获取排除项 + const keys = Object.keys(window[type]) + const defaultExcludes = ['dynamicRouter', 'serverDynamicRouter'] + const excludesArr = excludes ? [...excludes, ...defaultExcludes] : defaultExcludes + const excludesKeys = excludesArr ? keys.filter((key) => !excludesArr.includes(key)) : keys + // 排除项不清除 + excludesKeys.forEach((key) => { + window[type].removeItem(key) + }) + // window[type].clear() + } + + return { + setStorage, + getStorage, + removeStorage, + clear + } +} diff --git a/src/hooks/web/useTable.ts b/src/hooks/web/useTable.ts new file mode 100644 index 000000000..eaa75dd43 --- /dev/null +++ b/src/hooks/web/useTable.ts @@ -0,0 +1,193 @@ +import { useI18n } from '@/hooks/web/useI18n' +import { Table, TableExpose, TableProps, TableSetProps, TableColumn } from '@/components/Table' +import { ElTable, ElMessageBox, ElMessage } from 'element-plus' +import { ref, watch, unref, nextTick, onMounted } from 'vue' + +const { t } = useI18n() + +interface UseTableConfig { + /** + * 是否初始化的时候请求一次 + */ + immediate?: boolean + fetchDataApi: () => Promise<{ + list: any[] + total?: number + }> + fetchDelApi?: () => Promise +} + +export const useTable = (config: UseTableConfig) => { + const { immediate = true } = config + + const loading = ref(false) + const currentPage = ref(1) + const pageSize = ref(10) + const total = ref(0) + const dataList = ref([]) + + watch( + () => currentPage.value, + () => { + methods.getList() + } + ) + + watch( + () => pageSize.value, + () => { + // 当前页不为1时,修改页数后会导致多次调用getList方法 + if (unref(currentPage) === 1) { + methods.getList() + } else { + currentPage.value = 1 + methods.getList() + } + } + ) + + onMounted(() => { + if (immediate) { + methods.getList() + } + }) + + // Table实例 + const tableRef = ref() + + // ElTable实例 + const elTableRef = ref>() + + const register = (ref: typeof Table & TableExpose, elRef: ComponentRef) => { + tableRef.value = ref + elTableRef.value = unref(elRef) + } + + const getTable = async () => { + await nextTick() + const table = unref(tableRef) + if (!table) { + console.error('The table is not registered. Please use the register method to register') + } + return table + } + + const methods = { + /** + * 获取表单数据 + */ + getList: async () => { + loading.value = true + try { + const res = await config?.fetchDataApi() + console.log('fetchDataApi res', res) + if (res) { + dataList.value = res.list + total.value = res.total || 0 + } + } catch (err) { + console.log('fetchDataApi error') + } finally { + loading.value = false + } + }, + + /** + * @description 设置table组件的props + * @param props table组件的props + */ + setProps: async (props: TableProps = {}) => { + const table = await getTable() + table?.setProps(props) + }, + + /** + * @description 设置column + * @param columnProps 需要设置的列 + */ + setColumn: async (columnProps: TableSetProps[]) => { + const table = await getTable() + table?.setColumn(columnProps) + }, + + /** + * @description 新增column + * @param tableColumn 需要新增数据 + * @param index 在哪里新增 + */ + addColumn: async (tableColumn: TableColumn, index?: number) => { + const table = await getTable() + table?.addColumn(tableColumn, index) + }, + + /** + * @description 删除column + * @param field 删除哪个数据 + */ + delColumn: async (field: string) => { + const table = await getTable() + table?.delColumn(field) + }, + + /** + * @description 获取ElTable组件的实例 + * @returns ElTable instance + */ + getElTableExpose: async () => { + await getTable() + return unref(elTableRef) + }, + + refresh: () => { + methods.getList() + }, + + // sortableChange: (e: any) => { + // console.log('sortableChange', e) + // const { oldIndex, newIndex } = e + // dataList.value.splice(newIndex, 0, dataList.value.splice(oldIndex, 1)[0]) + // // to do something + // } + // 删除数据 + delList: async (idsLength: number) => { + const { fetchDelApi } = config + if (!fetchDelApi) { + console.warn('fetchDelApi is undefined') + return + } + ElMessageBox.confirm(t('common.delMessage'), t('common.delWarning'), { + confirmButtonText: t('common.delOk'), + cancelButtonText: t('common.delCancel'), + type: 'warning' + }).then(async () => { + const res = await fetchDelApi() + if (res) { + ElMessage.success(t('common.delSuccess')) + + // 计算出临界点 + const current = + unref(total) % unref(pageSize) === idsLength || unref(pageSize) === 1 + ? unref(currentPage) > 1 + ? unref(currentPage) - 1 + : unref(currentPage) + : unref(currentPage) + + currentPage.value = current + methods.getList() + } + }) + } + } + + return { + tableRegister: register, + tableMethods: methods, + tableState: { + currentPage, + pageSize, + total, + dataList, + loading + } + } +} diff --git a/src/hooks/web/useTagsView.ts b/src/hooks/web/useTagsView.ts new file mode 100644 index 000000000..31eadb027 --- /dev/null +++ b/src/hooks/web/useTagsView.ts @@ -0,0 +1,63 @@ +import { useTagsViewStoreWithOut } from '@/store/modules/tagsView' +import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router' +import { computed, nextTick, unref } from 'vue' + +export const useTagsView = () => { + const tagsViewStore = useTagsViewStoreWithOut() + + const { replace, currentRoute } = useRouter() + + const selectedTag = computed(() => tagsViewStore.getSelectedTag) + + const closeAll = (callback?: Fn) => { + tagsViewStore.delAllViews() + callback?.() + } + + const closeLeft = (callback?: Fn) => { + tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeRight = (callback?: Fn) => { + tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeOther = (callback?: Fn) => { + tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeCurrent = (view?: RouteLocationNormalizedLoaded, callback?: Fn) => { + if (view?.meta?.affix) return + tagsViewStore.delView(view || unref(currentRoute)) + + callback?.() + } + + const refreshPage = async (view?: RouteLocationNormalizedLoaded, callback?: Fn) => { + tagsViewStore.delCachedView() + const { path, query } = view || unref(currentRoute) + await nextTick() + replace({ + path: '/redirect' + path, + query: query + }) + callback?.() + } + + const setTitle = (title: string, path?: string) => { + tagsViewStore.setTitle(title, path) + } + + return { + closeAll, + closeLeft, + closeRight, + closeOther, + closeCurrent, + refreshPage, + setTitle + } +} diff --git a/src/hooks/web/useTimeAgo.ts b/src/hooks/web/useTimeAgo.ts new file mode 100644 index 000000000..5675e5e1f --- /dev/null +++ b/src/hooks/web/useTimeAgo.ts @@ -0,0 +1,50 @@ +import { useTimeAgo as useTimeAgoCore, UseTimeAgoMessages } from '@vueuse/core' +import { computed, unref } from 'vue' +import { useLocaleStoreWithOut } from '@/store/modules/locale' + +const TIME_AGO_MESSAGE_MAP: { + 'zh-CN': UseTimeAgoMessages + en: UseTimeAgoMessages +} = { + 'zh-CN': { + justNow: '刚刚', + invalid: '无效时间', + past: (n) => (n.match(/\d/) ? `${n}前` : n), + future: (n) => (n.match(/\d/) ? `${n}后` : n), + month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`), + year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`), + day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`), + week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`), + hour: (n) => `${n} 小时`, + minute: (n) => `${n} 分钟`, + second: (n) => `${n} 秒` + }, + en: { + justNow: '刚刚', + invalid: 'Invalid Date', + past: (n) => (n.match(/\d/) ? `${n} ago` : n), + future: (n) => (n.match(/\d/) ? `in ${n}` : n), + month: (n, past) => + n === 1 ? (past ? 'last month' : 'next month') : `${n} month${n > 1 ? 's' : ''}`, + year: (n, past) => + n === 1 ? (past ? 'last year' : 'next year') : `${n} year${n > 1 ? 's' : ''}`, + day: (n, past) => (n === 1 ? (past ? 'yesterday' : 'tomorrow') : `${n} day${n > 1 ? 's' : ''}`), + week: (n, past) => + n === 1 ? (past ? 'last week' : 'next week') : `${n} week${n > 1 ? 's' : ''}`, + hour: (n) => `${n} hour${n > 1 ? 's' : ''}`, + minute: (n) => `${n} minute${n > 1 ? 's' : ''}`, + second: (n) => `${n} second${n > 1 ? 's' : ''}` + } +} + +export const useTimeAgo = (time: Date | number | string) => { + const localeStore = useLocaleStoreWithOut() + + const currentLocale = computed(() => localeStore.getCurrentLocale) + + const timeAgo = useTimeAgoCore(time, { + messages: TIME_AGO_MESSAGE_MAP[unref(currentLocale).lang] + }) + + return timeAgo +} diff --git a/src/hooks/web/useTitle.ts b/src/hooks/web/useTitle.ts new file mode 100644 index 000000000..546267d85 --- /dev/null +++ b/src/hooks/web/useTitle.ts @@ -0,0 +1,25 @@ +import { watch, ref } from 'vue' +import { isString } from '@/utils/is' +import { useAppStoreWithOut } from '@/store/modules/app' +import { useI18n } from '@/hooks/web/useI18n' + +export const useTitle = (newTitle?: string) => { + const { t } = useI18n() + const appStore = useAppStoreWithOut() + + const title = ref( + newTitle ? `${appStore.getTitle} - ${t(newTitle as string)}` : appStore.getTitle + ) + + watch( + title, + (n, o) => { + if (isString(n) && n !== o && document) { + document.title = n + } + }, + { immediate: true } + ) + + return title +} diff --git a/src/hooks/web/useValidator.ts b/src/hooks/web/useValidator.ts new file mode 100644 index 000000000..00586bdce --- /dev/null +++ b/src/hooks/web/useValidator.ts @@ -0,0 +1,109 @@ +import { useI18n } from '@/hooks/web/useI18n' +import { FormItemRule } from 'element-plus' + +const { t } = useI18n() + +interface LengthRange { + min: number + max: number + message?: string +} + +export const useValidator = () => { + const required = (message?: string): FormItemRule => { + return { + required: true, + message: message || t('common.required') + } + } + + const lengthRange = (options: LengthRange): FormItemRule => { + const { min, max, message } = options + + return { + min, + max, + message: message || t('common.lengthRange', { min, max }) + } + } + + const notSpace = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (val?.indexOf(' ') !== -1) { + callback(new Error(message || t('common.notSpace'))) + } else { + callback() + } + } + } + } + + const notSpecialCharacters = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(val)) { + callback(new Error(message || t('common.notSpecialCharacters'))) + } else { + callback() + } + } + } + } + + const phone = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (!val) return callback() + if (!/^1[3456789]\d{9}$/.test(val)) { + callback(new Error(message || '请输入正确的手机号码')) + } else { + callback() + } + } + } + } + + const email = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (!val) return callback() + if (!/^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(val)) { + callback(new Error(message || '请输入正确的邮箱')) + } else { + callback() + } + } + } + } + + const maxlength = (max: number): FormItemRule => { + return { + max, + message: '长度不能超过' + max + '个字符' + } + } + + const check = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (!val) { + callback(new Error(message || t('common.required'))) + } else { + callback() + } + } + } + } + + return { + required, + lengthRange, + notSpace, + notSpecialCharacters, + phone, + email, + maxlength, + check + } +} diff --git a/src/hooks/web/useWatermark.ts b/src/hooks/web/useWatermark.ts new file mode 100644 index 000000000..4a313594c --- /dev/null +++ b/src/hooks/web/useWatermark.ts @@ -0,0 +1,55 @@ +const domSymbol = Symbol('watermark-dom') + +export function useWatermark(appendEl: HTMLElement | null = document.body) { + let func: Fn = () => {} + const id = domSymbol.toString() + const clear = () => { + const domId = document.getElementById(id) + if (domId) { + const el = appendEl + el && el.removeChild(domId) + } + window.removeEventListener('resize', func) + } + const createWatermark = (str: string) => { + clear() + + const can = document.createElement('canvas') + can.width = 300 + can.height = 240 + + const cans = can.getContext('2d') + if (cans) { + cans.rotate((-20 * Math.PI) / 120) + cans.font = '15px Vedana' + cans.fillStyle = 'rgba(0, 0, 0, 0.15)' + cans.textAlign = 'left' + cans.textBaseline = 'middle' + cans.fillText(str, can.width / 20, can.height) + } + + const div = document.createElement('div') + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '0px' + div.style.left = '0px' + div.style.position = 'absolute' + div.style.zIndex = '100000000' + div.style.width = document.documentElement.clientWidth + 'px' + div.style.height = document.documentElement.clientHeight + 'px' + div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat' + const el = appendEl + el && el.appendChild(div) + return id + } + + function setWatermark(str: string) { + createWatermark(str) + func = () => { + createWatermark(str) + } + window.addEventListener('resize', func) + } + + return { setWatermark, clear } +} diff --git a/src/layout/Layout.vue b/src/layout/Layout.vue new file mode 100644 index 000000000..8f570c39b --- /dev/null +++ b/src/layout/Layout.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/layout/components/AppView.vue b/src/layout/components/AppView.vue new file mode 100644 index 000000000..c491f1e5f --- /dev/null +++ b/src/layout/components/AppView.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/layout/components/ToolHeader.vue b/src/layout/components/ToolHeader.vue new file mode 100644 index 000000000..e6f953f1f --- /dev/null +++ b/src/layout/components/ToolHeader.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/layout/components/useRenderLayout.tsx b/src/layout/components/useRenderLayout.tsx new file mode 100644 index 000000000..9f4b3a722 --- /dev/null +++ b/src/layout/components/useRenderLayout.tsx @@ -0,0 +1,306 @@ +import { computed } from 'vue' +import { useAppStore } from '@/store/modules/app' +import { Menu } from '@/components/Menu' +import { TabMenu } from '@/components/TabMenu' +import { TagsView } from '@/components/TagsView' +import { Logo } from '@/components/Logo' +import AppView from './AppView.vue' +import ToolHeader from './ToolHeader.vue' +import { ElScrollbar } from 'element-plus' +import { useDesign } from '@/hooks/web/useDesign' + +const { getPrefixCls } = useDesign() + +const prefixCls = getPrefixCls('layout') + +const appStore = useAppStore() + +const pageLoading = computed(() => appStore.getPageLoading) + +// 标签页 +const tagsView = computed(() => appStore.getTagsView) + +// 菜单折叠 +const collapse = computed(() => appStore.getCollapse) + +// logo +const logo = computed(() => appStore.logo) + +// 固定头部 +const fixedHeader = computed(() => appStore.getFixedHeader) + +// 是否是移动端 +const mobile = computed(() => appStore.getMobile) + +// 固定菜单 +const fixedMenu = computed(() => appStore.getFixedMenu) + +export const useRenderLayout = () => { + const renderClassic = () => { + return ( + <> +
+ {logo.value ? ( + + ) : undefined} + +
+
+ +
+ + + {tagsView.value ? ( + + ) : undefined} +
+ + +
+
+ + ) + } + + const renderTopLeft = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ +
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+
+ + ) + } + + const renderTop = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+ + ) + } + + const renderCutMenu = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ +
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+
+ + ) + } + + return { + renderClassic, + renderTopLeft, + renderTop, + renderCutMenu + } +} diff --git a/src/locales/en.ts b/src/locales/en.ts new file mode 100644 index 000000000..f26eb8f26 --- /dev/null +++ b/src/locales/en.ts @@ -0,0 +1,578 @@ +export default { + common: { + inputText: 'Please input', + selectText: 'Please select', + startTimeText: 'Start time', + endTimeText: 'End time', + login: 'Login', + required: 'This is required', + loginOut: 'Login out', + document: 'Document', + reminder: 'Reminder', + loginOutMessage: 'Exit the system?', + back: 'Back', + ok: 'OK', + cancel: 'Cancel', + reload: 'Reload current', + closeTab: 'Close current', + closeTheLeftTab: 'Close left', + closeTheRightTab: 'Close right', + closeOther: 'Close other', + closeAll: 'Close all', + prevLabel: 'Prev', + nextLabel: 'Next', + skipLabel: 'Jump', + doneLabel: 'End', + menu: 'Menu', + menuDes: 'Menu bar rendered in routed structure', + collapse: 'Collapse', + collapseDes: 'Expand and zoom the menu bar', + tagsView: 'Tags view', + tagsViewDes: 'Used to record routing history', + tool: 'Tool', + toolDes: 'Used to set up custom systems', + query: 'Query', + reset: 'Reset', + shrink: 'Put away', + expand: 'Expand', + delMessage: 'Delete the selected data?', + delWarning: 'Warning', + delOk: 'OK', + delCancel: 'Cancel', + delNoData: 'Please select the data to delete', + delSuccess: 'Deleted successfully', + refresh: 'Refresh', + fullscreen: 'Fullscreen', + size: 'Size', + columnSetting: 'Column setting', + lengthRange: 'The length should be between {min} and {max}', + notSpace: 'Spaces are not allowed', + notSpecialCharacters: 'Special characters are not allowed', + isEqual: 'The two are not equal', + // 列设置 + setting: 'Setting' + }, + lock: { + lockScreen: 'Lock screen', + lock: 'Lock', + lockPassword: 'Lock screen password', + unlock: 'Click to unlock', + backToLogin: 'Back to login', + entrySystem: 'Entry the system', + placeholder: 'Please enter the lock screen password', + message: 'Lock screen password error' + }, + error: { + noPermission: `Sorry, you don't have permission to access this page.`, + pageError: 'Sorry, the page you visited does not exist.', + networkError: 'Sorry, the server reported an error.', + returnToHome: 'Return to home' + }, + setting: { + projectSetting: 'Project setting', + theme: 'Theme', + layout: 'Layout', + systemTheme: 'System theme', + menuTheme: 'Menu theme', + interfaceDisplay: 'Interface display', + breadcrumb: 'Breadcrumb', + breadcrumbIcon: 'Breadcrumb icon', + collapseMenu: 'Collapse menu', + hamburgerIcon: 'Hamburger icon', + screenfullIcon: 'Screenfull icon', + sizeIcon: 'Size icon', + localeIcon: 'Locale icon', + tagsView: 'Tags view', + logo: 'Logo', + greyMode: 'Grey mode', + fixedHeader: 'Fixed header', + headerTheme: 'Header theme', + cutMenu: 'Cut Menu', + copy: 'Copy', + clearAndReset: 'Clear cache and reset', + copySuccess: 'Copy success', + copyFailed: 'Copy failed', + footer: 'Footer', + uniqueOpened: 'Unique opened', + tagsViewIcon: 'Tags view icon', + // 开启动态路由 + dynamicRouter: 'Enable dynamic router', + serverDynamicRouter: 'Server dynamic router', + reExperienced: 'Please exit the login experience again', + fixedMenu: 'Fixed menu' + }, + size: { + default: 'Default', + large: 'Large', + small: 'Small' + }, + login: { + welcome: 'Welcome to the system', + message: 'Backstage management system', + username: 'Username', + password: 'Password', + register: 'Register', + checkPassword: 'Confirm password', + login: 'Sign in', + otherLogin: 'Sign in with', + remember: 'Remember me', + hasUser: 'Existing account? Go to login', + forgetPassword: 'Forget password', + usernamePlaceholder: 'Please input username', + passwordPlaceholder: 'Please input password', + code: 'Verification code', + codePlaceholder: 'Please input verification code', + getCode: 'Get code' + }, + router: { + login: 'Login', + level: 'Multi level menu', + menu: 'Menu', + menu1: 'Menu1', + menu11: 'Menu1-1', + menu111: 'Menu1-1-1', + menu12: 'Menu1-2', + menu2: 'Menu2', + dashboard: 'Dashboard', + analysis: 'Analysis', + workplace: 'Workplace', + guide: 'Guide', + component: 'Component', + icon: 'Icon', + echart: 'Echart', + countTo: 'Count to', + watermark: 'Watermark', + qrcode: 'Qrcode', + highlight: 'Highlight', + infotip: 'Infotip', + form: 'Form', + defaultForm: 'All examples', + search: 'Search', + table: 'Table', + defaultTable: 'Basic example', + editor: 'Editor', + richText: 'Rich text', + jsonEditor: 'JSON Editor', + codeEditor: 'Code Editor', + dialog: 'Dialog', + imageViewer: 'Image viewer', + descriptions: 'Descriptions', + example: 'Example', + exampleDialog: 'Example dialog', + examplePage: 'Example page', + exampleAdd: 'Example page - add', + exampleEdit: 'Example page - edit', + exampleDetail: 'Example page - detail', + errorPage: 'Error page', + authorization: 'Authorization', + user: 'User management', + role: 'Role management', + document: 'Document', + inputPassword: 'InputPassword', + sticky: 'Sticky', + treeTable: 'Tree table', + PicturePreview: 'Table Image Preview', + department: 'Department management', + menuManagement: 'Menu management', + // 权限测试页面 + permission: 'Permission test page', + function: 'Function', + multipleTabs: 'Multiple tabs', + details: 'Details', + iconPicker: 'Icon picker', + request: 'Request', + waterfall: 'Waterfall', + imageCropping: 'Image cropping', + videoPlayer: 'Video player', + // 表格视频预览 + tableVideoPreview: 'Table video preview', + cardTable: 'Card table', + personalCenter: 'Personal center', + personal: 'Personal', + avatars: 'Avatars', + iAgree: 'I agree' + }, + permission: { + hasPermission: 'Please set the operation permission value' + }, + analysis: { + newUser: 'New user', + unreadInformation: 'Unread information', + transactionAmount: 'Transaction amount', + totalShopping: 'Total Shopping', + monthlySales: 'Monthly sales', + userAccessSource: 'User access source', + january: 'January', + february: 'February', + march: 'March', + april: 'April', + may: 'May', + june: 'June', + july: 'July', + august: 'August', + september: 'September', + october: 'October', + november: 'November', + december: 'December', + estimate: 'Estimate', + actual: 'Actual', + directAccess: 'Airect access', + mailMarketing: 'Mail marketing', + allianceAdvertising: 'Alliance advertising', + videoAdvertising: 'Video advertising', + searchEngines: 'Search engines', + weeklyUserActivity: 'Weekly user activity', + activeQuantity: 'Active quantity', + monday: 'Monday', + tuesday: 'Tuesday', + wednesday: 'Wednesday', + thursday: 'Thursday', + friday: 'Friday', + saturday: 'Saturday', + sunday: 'Sunday' + }, + workplace: { + goodMorning: 'Good morning', + happyDay: 'Wish you happy every day!', + toady: `It's sunny today`, + project: 'Project', + access: 'Project access', + toDo: 'To do', + introduction: 'A serious introduction', + more: 'More', + shortcutOperation: 'Shortcut operation', + operation: 'Operation', + index: 'Index', + personal: 'Personal', + team: 'Team', + quote: 'Quote', + contribution: 'Contribution', + hot: 'Hot', + yield: 'Yield', + dynamic: 'Dynamic', + push: 'push', + pushCode: 'Archer push code to Github', + follow: 'Follow' + }, + formDemo: { + input: 'Input', + inputNumber: 'InputNumber', + default: 'Default', + icon: 'Icon', + mixed: 'Mixed', + password: 'Password', + textarea: 'Textarea', + remoteSearch: 'Remote search', + slot: 'Slot', + position: 'Position', + autocomplete: 'Autocomplete', + select: 'Select', + optionSlot: 'Option Slot', + selectGroup: 'Select Group', + selectV2: 'SelectV2', + cascader: 'Cascader', + switch: 'Switch', + rate: 'Rate', + colorPicker: 'Color Picker', + transfer: 'Transfer', + render: 'Render', + radio: 'Radio', + radioGroup: 'Radio Group', + button: 'Button', + checkbox: 'Checkbox', + checkboxButton: 'Checkbox Button', + checkboxGroup: 'Checkbox Group', + slider: 'Slider', + datePicker: 'Date Picker', + shortcuts: 'Shortcuts', + today: 'Today', + yesterday: 'Yesterday', + aWeekAgo: 'A week ago', + week: 'Week', + year: 'Year', + month: 'Month', + dates: 'Dates', + daterange: 'Date Range', + monthrange: 'Month Range', + dateTimePicker: 'DateTimePicker', + dateTimerange: 'Datetime Range', + timePicker: 'Time Picker', + timeSelect: 'Time Select', + inputPassword: 'input Password', + passwordStrength: 'Password Strength', + defaultForm: 'All examples', + formDes: + 'The secondary encapsulation of form components based on ElementPlus realizes data-driven and supports all Form parameters', + example: 'example', + operate: 'operate', + change: 'Change', + restore: 'Restore', + disabled: 'Disabled', + disablement: 'Disablement', + delete: 'Delete', + add: 'Add', + setValue: 'Set value', + resetValue: 'Reset value', + set: 'Set', + subitem: 'Subitem', + formValidation: 'Form validation', + verifyReset: 'Verify reset', + // 富文本编辑器 + richText: 'Rich text', + jsonEditor: 'JSON Editor', + form: 'Form', + // 远程加载 + remoteLoading: 'Remote loading', + // 聚焦 + focus: 'Focus', + treeSelect: 'Tree Select', + showCheckbox: 'Show Checkbox', + selectAnyLevel: 'Select Any Level', + multiple: 'Multiple', + filterable: 'Filterable', + // 自定义节点内容 + customContent: 'Custom content', + // 懒加载 + lazyLoad: 'Lazy load', + upload: 'Upload', + // 用户头像 + userAvatar: 'User avatar', + iconPicker: 'Icon picker', + iAgree: 'I agree' + }, + guideDemo: { + guide: 'Guide', + start: 'Start', + message: + 'The guide page is very useful for some people who enter the project for the first time. You can briefly introduce the functions of the project. The boot page is based on driver.js' + }, + iconDemo: { + icon: 'Icon', + localIcon: 'Local Icon', + iconify: 'Iconify component', + recommendedUse: 'Recommended use', + recommendeDes: + 'Iconify component basically contains all icons. You can query any icon you want. And packaging will only package the icons used.', + accessAddress: 'Access address' + }, + echartDemo: { + echart: 'Echart', + echartDes: + 'Based on the secondary packaging components of eckarts, the width is adaptive. The corresponding chart can be displayed by passing in the options and height attributes.' + }, + countToDemo: { + countTo: 'CountTo', + countToDes: + 'The transformation is based on vue-count-to and supports all vue-count-to parameters.', + suffix: 'Suffix', + prefix: 'Prefix', + separator: 'Separator', + duration: 'Duration', + endVal: 'End val', + startVal: 'Start val', + start: 'Start', + pause: 'Pause', + resume: 'Resume' + }, + watermarkDemo: { + watermark: 'Watermark', + createdWatermark: 'Created watermark', + clearWatermark: 'Clear watermark', + resetWatermark: 'Reset watermark' + }, + qrcodeDemo: { + qrcode: 'Qrcode', + qrcodeDes: 'Secondary packaging based on qrcode', + basicUsage: 'Basic usage', + imgTag: 'Img tag', + style: 'Style config', + click: 'Click event', + asynchronousContent: 'Asynchronous content', + invalid: 'Invalid', + logoConfig: 'Logo config', + logoStyle: 'Logo style', + size: 'size config' + }, + highlightDemo: { + highlight: 'Highlight', + message: 'The best time to plant a tree is ten years ago, followed by now.', + keys1: 'ten years ago', + keys2: 'now' + }, + infotipDemo: { + infotip: 'Infotip', + infotipDes: 'Secondary packaging of components based on Highlight', + title: 'matters needing attention' + }, + levelDemo: { + menu: 'Multi level menu cache' + }, + searchDemo: { + search: 'Search', + searchDes: + 'Based on the secondary encapsulation of form components, the functions of query and reset are realized', + operate: 'operate', + change: 'Change', + grid: 'grid', + button: 'Button', + restore: 'Restore', + inline: 'inline', + bottom: 'Bottom', + position: 'position', + left: 'left', + center: 'center', + right: 'right', + dynamicOptions: 'Dynamic options', + // 删除单选框 + deleteRadio: 'Delete radio', + // 还原单选框 + restoreRadio: 'Restore radio', + loading: 'Loading', + reset: 'Reset' + }, + stickyDemo: { + sticky: 'Sticky' + }, + tableDemo: { + table: 'Table', + tableDes: 'Secondary packaging of Table components based on ElementPlus', + index: 'Index', + title: 'Title', + author: 'Author', + displayTime: 'Display time', + importance: 'Importance', + pageviews: 'Pageviews', + action: 'Action', + important: 'Important', + good: 'Good', + commonly: 'Commonly', + operate: 'operate', + example: 'example', + show: 'Show', + hidden: 'Hidden', + pagination: 'pagination', + reserveIndex: 'Reserve index', + restoreIndex: 'Restore index', + showSelections: 'Show selections', + hiddenSelections: 'Restore selections', + showExpandedRows: 'Show expanded rows', + hiddenExpandedRows: 'Hidden expanded rows', + changeTitle: 'Change title', + header: 'Header', + selectAllNone: 'Select all / none', + delOrAddAction: 'Delete or add action', + showOrHiddenStripe: 'Show or hidden stripe', + showOrHiddenBorder: 'Show or hidden border', + fixedHeaderOrAuto: 'Fixed header or auto', + getSelections: 'Get selections', + preview: 'Preview', + showOrHiddenSortable: 'Show or hidden sortable', + videoPreview: 'Video preview', + cardTable: 'Card table' + }, + richText: { + richText: 'Rich text', + richTextDes: 'Secondary packaging based on wangeditor', + jsonEditor: 'JSON Editor', + jsonEditorDes: 'Secondary packaging based on vue-json-pretty', + codeEditor: 'Code Editor', + codeEditorDes: 'Secondary packaging based on monaco-editor' + }, + dialogDemo: { + dialog: 'Dialog', + resizeDialog: 'Resize dialog', + dialogDes: 'Secondary packaging of Dialog components based on ElementPlus', + open: 'Open', + close: 'Close', + combineWithForm: 'Combine with form', + submit: 'Submit' + }, + imageViewerDemo: { + open: 'Open', + imageViewer: 'Image viewer', + imageViewerDes: 'Secondary packaging of ImageViewer components based on ElementPlus' + }, + descriptionsDemo: { + descriptions: 'Descriptions', + descriptionsDes: 'Secondary packaging of Descriptions components based on ElementPlus', + username: 'Username', + nickName: 'NickName', + phone: 'Phone', + email: 'Email', + addr: 'Address', + form: 'Combined with Form component' + }, + exampleDemo: { + title: 'Title', + add: 'Add', + del: 'Delete', + edit: 'Edit', + author: 'Author', + displayTime: 'Display time', + importance: 'Importance', + pageviews: 'Pageviews', + important: 'Important', + content: 'Content', + save: 'Save', + detail: 'Detail' + }, + userDemo: { + title: 'User management', + message: + 'Because it is simulated data, only two accounts with different permissions are provided, which can be modified and combined by developers according to the actual situation.', + index: 'Index', + action: 'Action', + username: 'Username', + password: 'Password', + role: 'Role', + remark: 'Remark', + remarkMessage1: 'Back end control routing permission', + remarkMessage2: 'Front end control routing permission', + // 部门列表 + departmentList: 'Department list', + // 搜索部门 + searchDepartment: 'Search department', + account: 'Account', + email: 'Email', + createTime: 'Create time', + // 所属部门 + department: 'Department', + departmentName: 'Department name', + status: 'Status', + enable: 'Enable', + disable: 'Disable', + superiorDepartment: 'Superior department' + }, + menu: { + menuName: 'Menu name', + icon: 'Icon', + // 权限 + permission: 'Permission', + component: 'Component', + path: 'Path', + status: 'Status', + hidden: 'Hidden', + alwaysShow: 'Always show', + noCache: 'No cache', + breadcrumb: 'Breadcrumb', + affix: 'Affix', + noTagsView: 'No tags view', + activeMenu: 'Active menu', + canTo: 'Can to', + name: 'Name' + }, + role: { + roleName: 'Role name', + role: 'Role', + // 菜单分配 + menu: 'Menu allocation' + }, + inputPasswordDemo: { + title: 'InputPassword', + inputPasswordDes: 'Secondary packaging of Input components based on ElementPlus' + }, + avatarsDemo: { + title: + 'Avatar component for avatar list, secondary packaging based on element plus Avatar component' + } +} diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts new file mode 100644 index 000000000..3593ad749 --- /dev/null +++ b/src/locales/zh-CN.ts @@ -0,0 +1,578 @@ +export default { + common: { + inputText: '请输入', + selectText: '请选择', + startTimeText: '开始时间', + endTimeText: '结束时间', + login: '登录', + required: '该项为必填项', + loginOut: '退出系统', + document: '项目文档', + reminder: '温馨提示', + loginOutMessage: '是否退出本系统?', + back: '返回', + ok: '确定', + cancel: '取消', + reload: '重新加载', + closeTab: '关闭标签页', + closeTheLeftTab: '关闭左侧标签页', + closeTheRightTab: '关闭右侧标签页', + closeOther: '关闭其它标签页', + closeAll: '关闭全部标签页', + prevLabel: '上一步', + nextLabel: '下一步', + skipLabel: '跳过', + doneLabel: '结束', + menu: '菜单', + menuDes: '以路由的结构渲染的菜单栏', + collapse: '展开缩收', + collapseDes: '展开和缩放菜单栏', + tagsView: '标签页', + tagsViewDes: '用于记录路由历史记录', + tool: '工具', + toolDes: '用于设置定制系统', + query: '查询', + reset: '重置', + shrink: '收起', + expand: '展开', + delMessage: '是否删除所选中数据?', + delWarning: '提示', + delOk: '确定', + delCancel: '取消', + delNoData: '请选择需要删除的数据', + delSuccess: '删除成功', + refresh: '刷新', + fullscreen: '全屏', + size: '尺寸', + columnSetting: '列设置', + lengthRange: '长度在 {min} 到 {max} 个字符', + notSpace: '不能包含空格', + notSpecialCharacters: '不能包含特殊字符', + isEqual: '两次输入不一致', + setting: '设置' + }, + lock: { + lockScreen: '锁定屏幕', + lock: '锁定', + lockPassword: '锁屏密码', + unlock: '点击解锁', + backToLogin: '返回登录', + entrySystem: '进入系统', + placeholder: '请输入锁屏密码', + message: '锁屏密码错误' + }, + error: { + noPermission: `抱歉,您无权访问此页面。`, + pageError: '抱歉,您访问的页面不存在。', + networkError: '抱歉,服务器报告错误。', + returnToHome: '返回首页' + }, + setting: { + projectSetting: '项目配置', + theme: '主题', + layout: '布局', + systemTheme: '系统主题', + menuTheme: '菜单主题', + interfaceDisplay: '界面显示', + breadcrumb: '面包屑', + breadcrumbIcon: '面包屑图标', + collapseMenu: '折叠菜单', + hamburgerIcon: '折叠图标', + screenfullIcon: '全屏图标', + sizeIcon: '尺寸图标', + localeIcon: '多语言图标', + tagsView: '标签页', + logo: 'Logo', + greyMode: '灰色模式', + fixedHeader: '固定头部', + headerTheme: '头部主题', + cutMenu: '切割菜单', + copy: '拷贝', + clearAndReset: '清除缓存并且重置', + copySuccess: '拷贝成功', + copyFailed: '拷贝失败', + footer: '页脚', + uniqueOpened: '菜单手风琴', + tagsViewIcon: '标签页图标', + dynamicRouter: '开启动态路由', + serverDynamicRouter: '服务端动态路由', + reExperienced: '请重新退出登录体验', + fixedMenu: '固定菜单' + }, + size: { + default: '默认', + large: '大', + small: '小' + }, + login: { + welcome: '欢迎使用本系统', + message: '开箱即用的中后台管理系统', + tenantName: '租户', + tenantNamePlaceholder: '请输入租户名称', + username: '用户名', + password: '密码', + register: '注册', + checkPassword: '确认密码', + login: '登录', + otherLogin: '其它登录方式', + remember: '记住我', + hasUser: '已有账号?去登录', + forgetPassword: '忘记密码', + usernamePlaceholder: '请输入用户名', + passwordPlaceholder: '请输入密码', + code: '验证码', + codePlaceholder: '请输入验证码', + getCode: '获取验证码', + btnMobile: '手机登录', + btnQRCode: '二维码登录' + }, + captcha: { + verification: '请完成安全验证', + verifySuccess: '验证成功', + verifyFail: '验证失败,请重试', + verifyError: '验证错误,请重试', + loadFailed: '加载失败' + }, + router: { + login: '登录', + level: '多级菜单', + menu: '菜单', + menu1: '菜单1', + menu11: '菜单1-1', + menu111: '菜单1-1-1', + menu12: '菜单1-2', + menu2: '菜单2', + dashboard: '首页', + analysis: '分析页', + workplace: '工作台', + guide: '引导', + component: '组件', + icon: '图标', + echart: '图表', + countTo: '数字动画', + watermark: '水印', + qrcode: '二维码', + highlight: '高亮', + infotip: '信息提示', + form: '表单', + defaultForm: '全部示例', + search: '查询', + table: '表格', + defaultTable: '基础示例', + editor: '编辑器', + richText: '富文本', + jsonEditor: 'JSON编辑器', + codeEditor: '代码编辑器', + dialog: '弹窗', + imageViewer: '图片预览', + descriptions: '描述', + example: '综合示例', + exampleDialog: '综合示例 - 弹窗', + examplePage: '综合示例 - 页面', + exampleAdd: '综合示例 - 新增', + exampleEdit: '综合示例 - 编辑', + exampleDetail: '综合示例 - 详情', + errorPage: '错误页面', + authorization: '权限管理', + user: '用户管理', + role: '角色管理', + document: '文档', + inputPassword: '密码输入框', + sticky: '黏性', + treeTable: '树形表格', + PicturePreview: '表格图片预览', + department: '部门管理', + menuManagement: '菜单管理', + permission: '权限测试页', + function: '功能', + multipleTabs: '多开标签页', + details: '详情页', + iconPicker: '图标选择器', + request: '请求', + waterfall: '瀑布流', + imageCropping: '图片裁剪', + videoPlayer: '视频播放器', + tableVideoPreview: '表格视频预览', + cardTable: '卡片表格', + personalCenter: '个人中心', + personal: '个人', + avatars: '头像列表', + iAgree: '我同意' + }, + permission: { + hasPermission: '请设置操作权限值' + }, + analysis: { + newUser: '新增用户', + unreadInformation: '未读消息', + transactionAmount: '成交金额', + totalShopping: '购物总量', + monthlySales: '每月销售额', + userAccessSource: '用户访问来源', + january: '一月', + february: '二月', + march: '三月', + april: '四月', + may: '五月', + june: '六月', + july: '七月', + august: '八月', + september: '九月', + october: '十月', + november: '十一月', + december: '十二月', + estimate: '预计', + actual: '实际', + directAccess: '直接访问', + mailMarketing: '邮件营销', + allianceAdvertising: '联盟广告', + videoAdvertising: '视频广告', + searchEngines: '搜索引擎', + weeklyUserActivity: '每周用户活跃量', + activeQuantity: '活跃量', + monday: '周一', + tuesday: '周二', + wednesday: '周三', + thursday: '周四', + friday: '周五', + saturday: '周六', + sunday: '周日' + }, + workplace: { + goodMorning: '早安', + happyDay: '祝你开心每一天!', + toady: '今日晴', + project: '项目数', + access: '项目访问', + toDo: '待办', + introduction: '一个正经的简介', + more: '更多', + shortcutOperation: '快捷操作', + operation: '操作', + index: '指数', + personal: '个人', + team: '团队', + quote: '引用', + contribution: '贡献', + hot: '热度', + yield: '产量', + dynamic: '动态', + push: '推送', + pushCode: 'Archer 推送 代码到 Github', + follow: '关注' + }, + formDemo: { + input: '输入框', + inputNumber: '数字输入框', + default: '默认', + icon: '图标', + mixed: '复合型', + password: '密码框', + textarea: '多行文本', + remoteSearch: '远程搜索', + slot: '插槽', + position: '位置', + autocomplete: '自动补全', + select: '选择器', + optionSlot: '选项插槽', + selectGroup: '选项分组', + selectV2: '虚拟列表选择器', + cascader: '级联选择器', + switch: '开关', + rate: '评分', + colorPicker: '颜色选择器', + transfer: '穿梭框', + render: '渲染器', + radio: '单选框', + radioGroup: '单选框组', + button: '按钮', + checkbox: '多选框', + checkboxButton: '多选框按钮', + checkboxGroup: '多选框组', + slider: '滑块', + datePicker: '日期选择器', + shortcuts: '快捷选项', + today: '今天', + yesterday: '昨天', + aWeekAgo: '一周前', + week: '周', + year: '年', + month: '月', + dates: '日期', + daterange: '日期范围', + monthrange: '月份范围', + dateTimePicker: '日期时间选择器', + dateTimerange: '日期时间范围', + timePicker: '时间选择器', + timeSelect: '时间选择', + inputPassword: '密码输入框', + passwordStrength: '密码强度', + defaultForm: '全部示例', + formDes: '基于 ElementPlus 的 Form 组件二次封装,实现数据驱动,支持所有 Form 参数', + example: '示例', + operate: '操作', + change: '更改', + restore: '还原', + disabled: '禁用', + disablement: '解除禁用', + delete: '删除', + add: '添加', + setValue: '设置值', + resetValue: '重置值', + set: '设置', + subitem: '子项', + formValidation: '表单验证', + verifyReset: '验证重置', + // 富文本编辑器 + richText: '富文本编辑器', + // JSON编辑器 + jsonEditor: 'JSON编辑器', + form: '表单', + // 远程加载 + remoteLoading: '远程加载', + // 聚焦 + focus: '聚焦', + treeSelect: '树形选择器', + showCheckbox: '显示复选框', + selectAnyLevel: '选择任意级别', + multiple: '多选', + filterable: '可筛选', + customContent: '自定义内容', + lazyLoad: '懒加载', + upload: '上传', + userAvatar: '用户头像', + iconPicker: '图标选择器', + iAgree: '我同意' + }, + guideDemo: { + guide: '引导页', + start: '开始', + message: + '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。引导页基于 driver.js' + }, + iconDemo: { + icon: '图标', + localIcon: '本地图标', + iconify: 'Iconify组件', + recommendedUse: '推荐使用', + recommendeDes: + 'Iconify组件基本包含所有的图标,你可以查询到你想要的任何图标。并且打包只会打包所用到的图标。', + accessAddress: '访问地址' + }, + echartDemo: { + echart: '图表', + echartDes: + '基于 echarts 二次封装组件,自适应宽度,只需传入 options 与 height 属性即可展示对应的图表。' + }, + countToDemo: { + countTo: '数字动画', + countToDes: '基于 vue-count-to 进行改造,支持所有 vue-count-to 参数。', + suffix: '后缀', + prefix: '前缀', + separator: '分割符号', + duration: '持续时间', + endVal: '结束值', + startVal: '开始值', + start: '开始', + pause: '暂停', + resume: '继续' + }, + watermarkDemo: { + watermark: '水印', + createdWatermark: '创建水印', + clearWatermark: '清除水印', + resetWatermark: '重置水印' + }, + qrcodeDemo: { + qrcode: '二维码', + qrcodeDes: '基于 qrcode 二次封装', + basicUsage: '基础用法', + imgTag: 'img标签', + style: '样式配置', + click: '点击事件', + asynchronousContent: '异步内容', + invalid: '失效', + logoConfig: 'logo配置', + logoStyle: 'logo样式', + size: '大小配置' + }, + highlightDemo: { + highlight: '高亮', + message: '种一棵树最好的时间是十年前,其次就是现在。', + keys1: '十年前', + keys2: '现在' + }, + infotipDemo: { + infotip: '信息提示', + infotipDes: '基于 Highlight 组件二次封装', + title: '注意事项' + }, + levelDemo: { + menu: '多级菜单缓存' + }, + searchDemo: { + search: '查询', + searchDes: '基于 Form 组件二次封装,实现查询、重置功能', + operate: '操作', + change: '更改', + grid: '栅格', + button: '按钮', + restore: '还原', + inline: '内联', + bottom: '底部', + position: '位置', + left: '左', + center: '中', + right: '右', + dynamicOptions: '动态选项', + // 删除单选框 + deleteRadio: '删除单选框', + // 还原单选框 + restoreRadio: '还原单选框', + loading: '加载中', + reset: '重置' + }, + stickyDemo: { + sticky: '黏性' + }, + tableDemo: { + table: '表格', + tableDes: '基于 ElementPlus 的 Table 组件二次封装', + index: '序号', + title: '标题', + author: '作者', + displayTime: '创建时间', + importance: '重要性', + pageviews: '阅读数', + action: '操作', + important: '重要', + good: '良好', + commonly: '一般', + operate: '操作', + example: '示例', + show: '显示', + hidden: '隐藏', + pagination: '分页', + reserveIndex: '叠加序号', + restoreIndex: '还原序号', + showSelections: '显示多选', + hiddenSelections: '隐藏多选', + showExpandedRows: '显示展开行', + hiddenExpandedRows: '隐藏展开行', + changeTitle: '修改标题', + header: '头部', + selectAllNone: '全选/全不选', + delOrAddAction: '删除/添加操作列', + showOrHiddenStripe: '显示/隐藏斑马纹', + showOrHiddenBorder: '显示/隐藏边框', + fixedHeaderOrAuto: '固定头部/自动', + getSelections: '获取多选数据', + preview: '封面', + showOrHiddenSortable: '显示/隐藏排序', + videoPreview: '视频预览', + cardTable: '卡片表格' + }, + richText: { + richText: '富文本', + richTextDes: '基于 wangeditor 二次封装', + jsonEditor: 'JSON编辑器', + jsonEditorDes: '基于 vue-json-pretty 二次封装', + codeEditor: '代码编辑器', + codeEditorDes: '基于 monaco-editor 二次封装' + }, + dialogDemo: { + dialog: '弹窗', + resizeDialog: '可自定义调节弹窗大小的弹窗', + dialogDes: '基于 ElementPlus 的 Dialog 组件二次封装', + open: '打开', + close: '关闭', + combineWithForm: '与表单结合', + submit: '提交' + }, + imageViewerDemo: { + open: '打开', + imageViewer: '图片预览', + imageViewerDes: '基于 ElementPlus 的 ImageViewer 组件二次封装' + }, + descriptionsDemo: { + descriptions: '描述', + descriptionsDes: '基于 ElementPlus 的 Descriptions 组件二次封装', + username: '用户名', + nickName: '昵称', + phone: '联系电话', + email: '邮箱', + addr: '地址', + form: '与 Form 组件组合' + }, + exampleDemo: { + title: '标题', + add: '新增', + del: '删除', + edit: '编辑', + author: '作者', + displayTime: '创建时间', + importance: '重要性', + pageviews: '阅读数', + important: '重要', + content: '内容', + save: '保存', + detail: '详情' + }, + userDemo: { + title: '用户管理', + message: '由于是模拟数据,所以只提供了两种不同权限的帐号,开发者可根据实际情况自行改造结合。', + index: '序号', + action: '操作', + username: '用户名', + password: '密码', + role: '角色', + remark: '备注', + remarkMessage1: '后端控制路由权限', + remarkMessage2: '前端控制路由权限', + // 部门列表 + departmentList: '部门列表', + searchDepartment: '搜索部门', + account: '账号', + email: '邮箱', + createTime: '创建时间', + // 所属部门 + department: '所属部门', + departmentName: '部门名称', + status: '状态', + // 启用 + enable: '启用', + // 禁用 + disable: '禁用', + // 上级部门 + superiorDepartment: '上级部门' + }, + menu: { + menuName: '菜单名称', + icon: '图标', + permission: '按钮权限', + component: '组件', + path: '路径', + status: '状态', + hidden: '是否隐藏', + alwaysShow: '是否一直显示', + noCache: '是否清除缓存', + breadcrumb: '是否显示面包屑', + affix: '是否固定在标签页', + noTagsView: '是否隐藏标签页', + activeMenu: '高亮菜单', + canTo: '是否可跳转', + name: '组件名称' + }, + role: { + roleName: '角色名称', + role: '角色', + menu: '菜单分配' + }, + inputPasswordDemo: { + title: '密码输入框', + inputPasswordDes: '基于 ElementPlus 的 Input 组件二次封装' + }, + avatarsDemo: { + title: '头像列表组件,基于element-plus的Avatar组件二次封装' + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 000000000..7de5497c0 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,63 @@ +import 'vue/jsx' + +// 引入windi css +import '@/plugins/unocss' + +// 导入全局的svg图标 +import '@/plugins/svgIcon' + +// 初始化多语言 +import { setupI18n } from '@/plugins/vueI18n' + +// 引入状态管理 +import { setupStore } from '@/store' + +// 全局组件 +import { setupGlobCom } from '@/components' + +// 引入element-plus +import { setupElementPlus } from '@/plugins/elementPlus' + +// 引入全局样式 +import '@/styles/index.less' + +// 引入动画 +import '@/plugins/animate.css' + +// 路由 +import { setupRouter } from './router' + +// 权限 +import { setupPermission } from './directives' + +import { createApp } from 'vue' + +import App from './App.vue' + +import './permission' + +import { vtj } from '../package.json' +import { setupElementAdmin } from '@vtj/web' +import { IconsPlugin } from '@vtj/icons' +import '@vtj/web/src/index.scss' + +// 创建实例 +const setupAll = async () => { + const app = createApp(App) + await setupI18n(app) + setupStore(app) + setupGlobCom(app) + setupElementPlus(app) + setupRouter(app) + setupPermission(app) + app.use(IconsPlugin) + setupElementAdmin({ + id: vtj.id, + app, + ready: () => { + app.mount('#app') + } + }) +} + +setupAll() diff --git a/src/permission.ts b/src/permission.ts new file mode 100644 index 000000000..a14c3a833 --- /dev/null +++ b/src/permission.ts @@ -0,0 +1,64 @@ +import router from './router' +import { useAppStoreWithOut } from '@/store/modules/app' +import type { RouteRecordRaw } from 'vue-router' +import { useTitle } from '@/hooks/web/useTitle' +import { useNProgress } from '@/hooks/web/useNProgress' +import { usePermissionStoreWithOut } from '@/store/modules/permission' +import { usePageLoading } from '@/hooks/web/usePageLoading' +import { NO_REDIRECT_WHITE_LIST } from '@/constants' +import { useUserStoreWithOut } from '@/store/modules/user' + +const { start, done } = useNProgress() + +const { loadStart, loadDone } = usePageLoading() + +router.beforeEach(async (to, from, next) => { + start() + loadStart() + const permissionStore = usePermissionStoreWithOut() + const appStore = useAppStoreWithOut() + const userStore = useUserStoreWithOut() + if (userStore.getUserInfo) { + if (to.path === '/login') { + next({ path: '/' }) + } else { + if (permissionStore.getIsAddRouters) { + next() + return + } + + // 开发者可根据实际情况进行修改 + const roleRouters = userStore.getRoleRouters || [] + + // 是否使用动态路由 + if (appStore.getDynamicRouter) { + appStore.serverDynamicRouter + ? await permissionStore.generateRoutes('server', roleRouters as AppCustomRouteRecordRaw[]) + : await permissionStore.generateRoutes('frontEnd', roleRouters as string[]) + } else { + await permissionStore.generateRoutes('static') + } + + permissionStore.getAddRouters.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 + }) + const redirectPath = from.query.redirect || to.path + const redirect = decodeURIComponent(redirectPath as string) + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } + permissionStore.setIsAddRouters(true) + next(nextData) + } + } else { + if (NO_REDIRECT_WHITE_LIST.indexOf(to.path) !== -1) { + next() + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } +}) + +router.afterEach((to) => { + useTitle(to?.meta?.title as string) + done() // 结束Progress + loadDone() +}) diff --git a/src/plugins/animate.css/index.ts b/src/plugins/animate.css/index.ts new file mode 100644 index 000000000..3e9345131 --- /dev/null +++ b/src/plugins/animate.css/index.ts @@ -0,0 +1 @@ +import 'animate.css' diff --git a/src/plugins/echarts/index.ts b/src/plugins/echarts/index.ts new file mode 100644 index 000000000..34f756f64 --- /dev/null +++ b/src/plugins/echarts/index.ts @@ -0,0 +1,41 @@ +import * as echarts from 'echarts/core' + +import { + BarChart, + LineChart, + PieChart, + MapChart, + PictorialBarChart, + RadarChart +} from 'echarts/charts' + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent +} from 'echarts/components' + +import { CanvasRenderer } from 'echarts/renderers' + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + CanvasRenderer, + PictorialBarChart, + RadarChart +]) + +export default echarts diff --git a/src/plugins/elementPlus/index.ts b/src/plugins/elementPlus/index.ts new file mode 100644 index 000000000..29a7840a2 --- /dev/null +++ b/src/plugins/elementPlus/index.ts @@ -0,0 +1,24 @@ +import type { App } from 'vue' + +// 需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题 +import { ElLoading, ElScrollbar } from 'element-plus' + +const plugins = [ElLoading] + +const components = [ElScrollbar] + +export const setupElementPlus = (app: App) => { + plugins.forEach((plugin) => { + app.use(plugin) + }) + + // 为了开发环境启动更快,一次性引入所有样式 + if (import.meta.env.VITE_USE_ALL_ELEMENT_PLUS_STYLE === 'true') { + import('element-plus/dist/index.css') + return + } + + components.forEach((component) => { + app.component(component.name!, component) + }) +} diff --git a/src/plugins/svgIcon/index.ts b/src/plugins/svgIcon/index.ts new file mode 100644 index 000000000..1b11e2db2 --- /dev/null +++ b/src/plugins/svgIcon/index.ts @@ -0,0 +1 @@ +import 'virtual:svg-icons-register' diff --git a/src/plugins/unocss/index.ts b/src/plugins/unocss/index.ts new file mode 100644 index 000000000..d366b5a2f --- /dev/null +++ b/src/plugins/unocss/index.ts @@ -0,0 +1 @@ +import 'virtual:uno.css' diff --git a/src/plugins/vueI18n/helper.ts b/src/plugins/vueI18n/helper.ts new file mode 100644 index 000000000..da6bc8c90 --- /dev/null +++ b/src/plugins/vueI18n/helper.ts @@ -0,0 +1,3 @@ +export const setHtmlPageLang = (locale: LocaleType) => { + document.querySelector('html')?.setAttribute('lang', locale) +} diff --git a/src/plugins/vueI18n/index.ts b/src/plugins/vueI18n/index.ts new file mode 100644 index 000000000..f845b13f7 --- /dev/null +++ b/src/plugins/vueI18n/index.ts @@ -0,0 +1,42 @@ +import type { App } from 'vue' +import { createI18n } from 'vue-i18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import type { I18n, I18nOptions } from 'vue-i18n' +import { setHtmlPageLang } from './helper' + +export let i18n: ReturnType + +const createI18nOptions = async (): Promise => { + const localeStore = useLocaleStoreWithOut() + const locale = localeStore.getCurrentLocale + const localeMap = localeStore.getLocaleMap + const defaultLocal = await import(`../../locales/${locale.lang}.ts`) + const message = defaultLocal.default ?? {} + + setHtmlPageLang(locale.lang) + + localeStore.setCurrentLocale({ + lang: locale.lang + // elLocale: elLocal + }) + + return { + legacy: false, + locale: locale.lang, + fallbackLocale: locale.lang, + messages: { + [locale.lang]: message + }, + availableLocales: localeMap.map((v) => v.lang), + sync: true, + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true + } +} + +export const setupI18n = async (app: App) => { + const options = await createI18nOptions() + i18n = createI18n(options) as I18n + app.use(i18n) +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 000000000..d8967808e --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,760 @@ +import { createRouter, createWebHashHistory } from 'vue-router' +import type { RouteRecordRaw } from 'vue-router' +import type { App } from 'vue' +import { Layout, getParentLayout } from '@/utils/routerHelper' +import { useI18n } from '@/hooks/web/useI18n' +import { NO_RESET_WHITE_LIST } from '@/constants' +import { vtj } from '../../package.json' +import { setupElementAdminRoutes } from '@vtj/web' + +const { t } = useI18n() +export const constantRouterMap: AppRouteRecordRaw[] = [ + { + path: '/', + component: Layout, + redirect: '/dashboard/analysis', + name: 'Root', + meta: { + hidden: true + } + }, + { + path: '/redirect', + component: Layout, + name: 'RedirectParent', + children: [ + { + path: '/redirect/:path(.*)', + name: 'Redirect', + component: () => import('@/views/Redirect/Redirect.vue'), + meta: {} + } + ], + meta: { + hidden: true, + noTagsView: true + } + }, + { + path: '/login', + component: () => import('@/views/Login/Login.vue'), + name: 'Login', + meta: { + hidden: true, + title: t('router.login'), + noTagsView: true + } + }, + { + path: '/personal', + component: Layout, + redirect: '/personal/personal-center', + name: 'Personal', + meta: { + title: t('router.personal'), + hidden: true, + canTo: true + }, + children: [ + { + path: 'personal-center', + component: () => import('@/views/Personal/PersonalCenter/PersonalCenter.vue'), + name: 'PersonalCenter', + meta: { + title: t('router.personalCenter'), + hidden: true, + canTo: true + } + } + ] + }, + { + path: '/404', + component: () => import('@/views/Error/404.vue'), + name: 'NoFind', + meta: { + hidden: true, + title: '404', + noTagsView: true + } + } +] + +export const asyncRouterMap: AppRouteRecordRaw[] = [ + { + path: '/dashboard', + component: Layout, + redirect: '/dashboard/analysis', + name: 'Dashboard', + meta: { + title: t('router.dashboard'), + icon: 'vi-ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: () => import('@/views/Dashboard/Analysis.vue'), + name: 'Analysis', + meta: { + title: t('router.analysis'), + noCache: true, + affix: true + } + }, + { + path: 'workplace', + component: () => import('@/views/Dashboard/Workplace.vue'), + name: 'Workplace', + meta: { + title: t('router.workplace'), + noCache: true + } + } + ] + }, + { + path: '/external-link', + component: Layout, + meta: {}, + name: 'ExternalLink', + children: [ + { + path: 'https://element-plus-admin-doc.cn/', + name: 'DocumentLink', + meta: { + title: t('router.document'), + icon: 'vi-clarity:document-solid' + } + } + ] + }, + { + path: '/guide', + component: Layout, + name: 'Guide', + meta: {}, + children: [ + { + path: 'index', + component: () => import('@/views/Guide/Guide.vue'), + name: 'GuideDemo', + meta: { + title: t('router.guide'), + icon: 'vi-cib:telegram-plane' + } + } + ] + }, + { + path: '/components', + component: Layout, + name: 'ComponentsDemo', + meta: { + title: t('router.component'), + icon: 'vi-bx:bxs-component', + alwaysShow: true + }, + children: [ + { + path: 'form', + component: getParentLayout(), + redirect: '/components/form/default-form', + name: 'Form', + meta: { + title: t('router.form'), + alwaysShow: true + }, + children: [ + { + path: 'default-form', + component: () => import('@/views/Components/Form/DefaultForm.vue'), + name: 'DefaultForm', + meta: { + title: t('router.defaultForm') + } + }, + { + path: 'use-form', + component: () => import('@/views/Components/Form/UseFormDemo.vue'), + name: 'UseForm', + meta: { + title: 'UseForm' + } + } + ] + }, + { + path: 'table', + component: getParentLayout(), + redirect: '/components/table/default-table', + name: 'TableDemo', + meta: { + title: t('router.table'), + alwaysShow: true + }, + children: [ + { + path: 'default-table', + component: () => import('@/views/Components/Table/DefaultTable.vue'), + name: 'DefaultTable', + meta: { + title: t('router.defaultTable') + } + }, + { + path: 'use-table', + component: () => import('@/views/Components/Table/UseTableDemo.vue'), + name: 'UseTable', + meta: { + title: 'UseTable' + } + }, + { + path: 'tree-table', + component: () => import('@/views/Components/Table/TreeTable.vue'), + name: 'TreeTable', + meta: { + title: t('router.treeTable') + } + }, + { + path: 'table-image-preview', + component: () => import('@/views/Components/Table/TableImagePreview.vue'), + name: 'TableImagePreview', + meta: { + title: t('router.PicturePreview') + } + }, + { + path: 'table-video-preview', + component: () => import('@/views/Components/Table/TableVideoPreview.vue'), + name: 'TableVideoPreview', + meta: { + title: t('router.tableVideoPreview') + } + }, + { + path: 'card-table', + component: () => import('@/views/Components/Table/CardTable.vue'), + name: 'CardTable', + meta: { + title: t('router.cardTable') + } + } + ] + }, + { + path: 'editor-demo', + component: getParentLayout(), + redirect: '/components/editor-demo/editor', + name: 'EditorDemo', + meta: { + title: t('router.editor'), + alwaysShow: true + }, + children: [ + { + path: 'editor', + component: () => import('@/views/Components/Editor/Editor.vue'), + name: 'Editor', + meta: { + title: t('router.richText') + } + }, + { + path: 'json-editor', + component: () => import('@/views/Components/Editor/JsonEditor.vue'), + name: 'JsonEditor', + meta: { + title: t('router.jsonEditor') + } + } + ] + }, + { + path: 'search', + component: () => import('@/views/Components/Search.vue'), + name: 'Search', + meta: { + title: t('router.search') + } + }, + { + path: 'descriptions', + component: () => import('@/views/Components/Descriptions.vue'), + name: 'Descriptions', + meta: { + title: t('router.descriptions') + } + }, + { + path: 'image-viewer', + component: () => import('@/views/Components/ImageViewer.vue'), + name: 'ImageViewer', + meta: { + title: t('router.imageViewer') + } + }, + { + path: 'dialog', + component: () => import('@/views/Components/Dialog.vue'), + name: 'Dialog', + meta: { + title: t('router.dialog') + } + }, + { + path: 'icon', + component: () => import('@/views/Components/Icon.vue'), + name: 'Icon', + meta: { + title: t('router.icon') + } + }, + { + path: 'icon-picker', + component: () => import('@/views/Components/IconPicker.vue'), + name: 'IconPicker', + meta: { + title: t('router.iconPicker') + } + }, + { + path: 'echart', + component: () => import('@/views/Components/Echart.vue'), + name: 'Echart', + meta: { + title: t('router.echart') + } + }, + { + path: 'count-to', + component: () => import('@/views/Components/CountTo.vue'), + name: 'CountTo', + meta: { + title: t('router.countTo') + } + }, + { + path: 'qrcode', + component: () => import('@/views/Components/Qrcode.vue'), + name: 'Qrcode', + meta: { + title: t('router.qrcode') + } + }, + { + path: 'highlight', + component: () => import('@/views/Components/Highlight.vue'), + name: 'Highlight', + meta: { + title: t('router.highlight') + } + }, + { + path: 'infotip', + component: () => import('@/views/Components/Infotip.vue'), + name: 'Infotip', + meta: { + title: t('router.infotip') + } + }, + { + path: 'input-password', + component: () => import('@/views/Components/InputPassword.vue'), + name: 'InputPassword', + meta: { + title: t('router.inputPassword') + } + }, + { + path: 'waterfall', + component: () => import('@/views/Components/Waterfall.vue'), + name: 'waterfall', + meta: { + title: t('router.waterfall') + } + }, + { + path: 'image-cropping', + component: () => import('@/views/Components/ImageCropping.vue'), + name: 'ImageCropping', + meta: { + title: t('router.imageCropping') + } + }, + { + path: 'video-player', + component: () => import('@/views/Components/VideoPlayer.vue'), + name: 'VideoPlayer', + meta: { + title: t('router.videoPlayer') + } + }, + { + path: 'avatars', + component: () => import('@/views/Components/Avatars.vue'), + name: 'Avatars', + meta: { + title: t('router.avatars') + } + }, + { + path: 'i-agree', + component: () => import('@/views/Components/IAgree.vue'), + name: 'IAgree', + meta: { + title: t('router.iAgree') + } + } + ] + }, + { + path: '/function', + component: Layout, + redirect: '/function/multipleTabs', + name: 'Function', + meta: { + title: t('router.function'), + icon: 'vi-ri:function-fill', + alwaysShow: true + }, + children: [ + { + path: 'multiple-tabs', + component: () => import('@/views/Function/MultipleTabs.vue'), + name: 'MultipleTabs', + meta: { + title: t('router.multipleTabs') + } + }, + { + path: 'multiple-tabs-demo/:id', + component: () => import('@/views/Function/MultipleTabsDemo.vue'), + name: 'MultipleTabsDemo', + meta: { + hidden: true, + title: t('router.details'), + canTo: true, + activeMenu: '/function/multiple-tabs' + } + }, + { + path: 'request', + component: () => import('@/views/Function/Request.vue'), + name: 'Request', + meta: { + title: t('router.request') + } + }, + { + path: 'test', + component: () => import('@/views/Function/Test.vue'), + name: 'Test', + meta: { + title: t('router.permission'), + permission: ['add', 'edit', 'delete'] + } + } + ] + }, + { + path: '/hooks', + component: Layout, + redirect: '/hooks/useWatermark', + name: 'Hooks', + meta: { + title: 'hooks', + icon: 'vi-ic:outline-webhook', + alwaysShow: true + }, + children: [ + { + path: 'useWatermark', + component: () => import('@/views/hooks/useWatermark.vue'), + name: 'UseWatermark', + meta: { + title: 'useWatermark' + } + }, + { + path: 'useTagsView', + component: () => import('@/views/hooks/useTagsView.vue'), + name: 'UseTagsView', + meta: { + title: 'useTagsView' + } + }, + { + path: 'useValidator', + component: () => import('@/views/hooks/useValidator.vue'), + name: 'UseValidator', + meta: { + title: 'useValidator' + } + }, + { + path: 'useCrudSchemas', + component: () => import('@/views/hooks/useCrudSchemas.vue'), + name: 'UseCrudSchemas', + meta: { + title: 'useCrudSchemas' + } + }, + { + path: 'useClipboard', + component: () => import('@/views/hooks/useClipboard.vue'), + name: 'UseClipboard', + meta: { + title: 'useClipboard' + } + }, + { + path: 'useNetwork', + component: () => import('@/views/hooks/useNetwork.vue'), + name: 'UseNetwork', + meta: { + title: 'useNetwork' + } + } + ] + }, + { + path: '/level', + component: Layout, + redirect: '/level/menu1/menu1-1/menu1-1-1', + name: 'Level', + meta: { + title: t('router.level'), + icon: 'vi-carbon:skill-level-advanced' + }, + children: [ + { + path: 'menu1', + name: 'Menu1', + component: getParentLayout(), + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: t('router.menu1') + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + component: getParentLayout(), + redirect: '/level/menu1/menu1-1/menu1-1-1', + meta: { + title: t('router.menu11'), + alwaysShow: true + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + component: () => import('@/views/Level/Menu111.vue'), + meta: { + title: t('router.menu111') + } + } + ] + }, + { + path: 'menu1-2', + name: 'Menu12', + component: () => import('@/views/Level/Menu12.vue'), + meta: { + title: t('router.menu12') + } + } + ] + }, + { + path: 'menu2', + name: 'Menu2', + component: () => import('@/views/Level/Menu2.vue'), + meta: { + title: t('router.menu2') + } + } + ] + }, + { + path: '/example', + component: Layout, + redirect: '/example/example-dialog', + name: 'Example', + meta: { + title: t('router.example'), + icon: 'vi-ep:management', + alwaysShow: true + }, + children: [ + { + path: 'example-dialog', + component: () => import('@/views/Example/Dialog/ExampleDialog.vue'), + name: 'ExampleDialog', + meta: { + title: t('router.exampleDialog') + } + }, + { + path: 'example-page', + component: () => import('@/views/Example/Page/ExamplePage.vue'), + name: 'ExamplePage', + meta: { + title: t('router.examplePage') + } + }, + { + path: 'example-add', + component: () => import('@/views/Example/Page/ExampleAdd.vue'), + name: 'ExampleAdd', + meta: { + title: t('router.exampleAdd'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-edit', + component: () => import('@/views/Example/Page/ExampleEdit.vue'), + name: 'ExampleEdit', + meta: { + title: t('router.exampleEdit'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + }, + { + path: 'example-detail', + component: () => import('@/views/Example/Page/ExampleDetail.vue'), + name: 'ExampleDetail', + meta: { + title: t('router.exampleDetail'), + noTagsView: true, + noCache: true, + hidden: true, + canTo: true, + activeMenu: '/example/example-page' + } + } + ] + }, + { + path: '/error', + component: Layout, + redirect: '/error/404', + name: 'Error', + meta: { + title: t('router.errorPage'), + icon: 'vi-ci:error', + alwaysShow: true + }, + children: [ + { + path: '404-demo', + component: () => import('@/views/Error/404.vue'), + name: '404Demo', + meta: { + title: '404' + } + }, + { + path: '403-demo', + component: () => import('@/views/Error/403.vue'), + name: '403Demo', + meta: { + title: '403' + } + }, + { + path: '500-demo', + component: () => import('@/views/Error/500.vue'), + name: '500Demo', + meta: { + title: '500' + } + } + ] + }, + { + path: '/authorization', + component: Layout, + redirect: '/authorization/user', + name: 'Authorization', + meta: { + title: t('router.authorization'), + icon: 'vi-eos-icons:role-binding', + alwaysShow: true + }, + children: [ + { + path: 'department', + component: () => import('@/views/Authorization/Department/Department.vue'), + name: 'Department', + meta: { + title: t('router.department') + } + }, + { + path: 'user', + component: () => import('@/views/Authorization/User/User.vue'), + name: 'User', + meta: { + title: t('router.user') + } + }, + { + path: 'menu', + component: () => import('@/views/Authorization/Menu/Menu.vue'), + name: 'Menu', + meta: { + title: t('router.menuManagement') + } + }, + { + path: 'role', + component: () => import('@/views/Authorization/Role/Role.vue'), + name: 'Role', + meta: { + title: t('router.role') + } + } + ] + } +] + +const router = createRouter({ + history: createWebHashHistory(), + strict: true, + routes: constantRouterMap as RouteRecordRaw[], + scrollBehavior: () => ({ left: 0, top: 0 }) +}) + +export const resetRouter = (): void => { + router.getRoutes().forEach((route) => { + const { name } = route + if (name && !NO_RESET_WHITE_LIST.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name) + } + }) +} + +export const setupRouter = async (app: App) => { + await setupElementAdminRoutes({ + id: vtj.id, + router, + routes: constantRouterMap, + layout: Layout + }) + app.use(router) +} + +export default router diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 000000000..ee92ca82d --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,13 @@ +import type { App } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +const store = createPinia() + +store.use(piniaPluginPersistedstate) + +export const setupStore = (app: App) => { + app.use(store) +} + +export { store } diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts new file mode 100644 index 000000000..0e7a8674b --- /dev/null +++ b/src/store/modules/app.ts @@ -0,0 +1,338 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { setCssVar, humpToUnderline } from '@/utils' +import { colorIsDark, hexToRGB, lighten, mix } from '@/utils/color' +import { ElMessage, ComponentSize } from 'element-plus' +import { useCssVar } from '@vueuse/core' +import { unref } from 'vue' +import { useDark } from '@vueuse/core' + +interface AppState { + breadcrumb: boolean + breadcrumbIcon: boolean + collapse: boolean + uniqueOpened: boolean + hamburger: boolean + screenfull: boolean + size: boolean + locale: boolean + tagsView: boolean + tagsViewIcon: boolean + logo: boolean + fixedHeader: boolean + greyMode: boolean + dynamicRouter: boolean + serverDynamicRouter: boolean + pageLoading: boolean + layout: LayoutType + title: string + isDark: boolean + currentSize: ComponentSize + sizeMap: ComponentSize[] + mobile: boolean + footer: boolean + theme: ThemeTypes + fixedMenu: boolean +} + +export const useAppStore = defineStore('app', { + state: (): AppState => { + return { + sizeMap: ['default', 'large', 'small'], + mobile: false, // 是否是移动端 + title: import.meta.env.VITE_APP_TITLE, // 标题 + pageLoading: false, // 路由跳转loading + breadcrumb: true, // 面包屑 + breadcrumbIcon: true, // 面包屑图标 + collapse: false, // 折叠菜单 + uniqueOpened: false, // 是否只保持一个子菜单的展开 + hamburger: true, // 折叠图标 + screenfull: true, // 全屏图标 + size: true, // 尺寸图标 + locale: true, // 多语言图标 + tagsView: true, // 标签页 + tagsViewIcon: true, // 是否显示标签图标 + logo: true, // logo + fixedHeader: true, // 固定toolheader + footer: true, // 显示页脚 + greyMode: false, // 是否开始灰色模式,用于特殊悼念日 + dynamicRouter: true, // 是否动态路由 + serverDynamicRouter: true, // 是否服务端渲染动态路由 + fixedMenu: false, // 是否固定菜单 + + layout: 'classic', // layout布局 + isDark: false, // 是否是暗黑模式 + currentSize: 'default', // 组件尺寸 + theme: { + // 主题色 + elColorPrimary: '#409eff', + // 左侧菜单边框颜色 + leftMenuBorderColor: 'inherit', + // 左侧菜单背景颜色 + leftMenuBgColor: '#001529', + // 左侧菜单浅色背景颜色 + leftMenuBgLightColor: '#0f2438', + // 左侧菜单选中背景颜色 + leftMenuBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单收起选中背景颜色 + leftMenuCollapseBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单字体颜色 + leftMenuTextColor: '#bfcbd9', + // 左侧菜单选中字体颜色 + leftMenuTextActiveColor: '#fff', + // logo字体颜色 + logoTitleTextColor: '#fff', + // logo边框颜色 + logoBorderColor: 'inherit', + // 头部背景颜色 + topHeaderBgColor: '#fff', + // 头部字体颜色 + topHeaderTextColor: 'inherit', + // 头部悬停颜色 + topHeaderHoverColor: '#f6f6f6', + // 头部边框颜色 + topToolBorderColor: '#eee' + } + } + }, + getters: { + getBreadcrumb(): boolean { + return this.breadcrumb + }, + getBreadcrumbIcon(): boolean { + return this.breadcrumbIcon + }, + getCollapse(): boolean { + return this.collapse + }, + getUniqueOpened(): boolean { + return this.uniqueOpened + }, + getHamburger(): boolean { + return this.hamburger + }, + getScreenfull(): boolean { + return this.screenfull + }, + getSize(): boolean { + return this.size + }, + getLocale(): boolean { + return this.locale + }, + getTagsView(): boolean { + return this.tagsView + }, + getTagsViewIcon(): boolean { + return this.tagsViewIcon + }, + getLogo(): boolean { + return this.logo + }, + getFixedHeader(): boolean { + return this.fixedHeader + }, + getGreyMode(): boolean { + return this.greyMode + }, + getDynamicRouter(): boolean { + return this.dynamicRouter + }, + getServerDynamicRouter(): boolean { + return this.serverDynamicRouter + }, + getFixedMenu(): boolean { + return this.fixedMenu + }, + getPageLoading(): boolean { + return this.pageLoading + }, + getLayout(): LayoutType { + return this.layout + }, + getTitle(): string { + return this.title + }, + getIsDark(): boolean { + return this.isDark + }, + getCurrentSize(): ComponentSize { + return this.currentSize + }, + getSizeMap(): ComponentSize[] { + return this.sizeMap + }, + getMobile(): boolean { + return this.mobile + }, + getTheme(): ThemeTypes { + return this.theme + }, + getFooter(): boolean { + return this.footer + } + }, + actions: { + setBreadcrumb(breadcrumb: boolean) { + this.breadcrumb = breadcrumb + }, + setBreadcrumbIcon(breadcrumbIcon: boolean) { + this.breadcrumbIcon = breadcrumbIcon + }, + setCollapse(collapse: boolean) { + this.collapse = collapse + }, + setUniqueOpened(uniqueOpened: boolean) { + this.uniqueOpened = uniqueOpened + }, + setHamburger(hamburger: boolean) { + this.hamburger = hamburger + }, + setScreenfull(screenfull: boolean) { + this.screenfull = screenfull + }, + setSize(size: boolean) { + this.size = size + }, + setLocale(locale: boolean) { + this.locale = locale + }, + setTagsView(tagsView: boolean) { + this.tagsView = tagsView + }, + setTagsViewIcon(tagsViewIcon: boolean) { + this.tagsViewIcon = tagsViewIcon + }, + setLogo(logo: boolean) { + this.logo = logo + }, + setFixedHeader(fixedHeader: boolean) { + this.fixedHeader = fixedHeader + }, + setGreyMode(greyMode: boolean) { + this.greyMode = greyMode + }, + setDynamicRouter(dynamicRouter: boolean) { + this.dynamicRouter = dynamicRouter + }, + setServerDynamicRouter(serverDynamicRouter: boolean) { + this.serverDynamicRouter = serverDynamicRouter + }, + setFixedMenu(fixedMenu: boolean) { + this.fixedMenu = fixedMenu + }, + setPageLoading(pageLoading: boolean) { + this.pageLoading = pageLoading + }, + setLayout(layout: LayoutType) { + if (this.mobile && layout !== 'classic') { + ElMessage.warning('移动端模式下不支持切换其它布局') + return + } + this.layout = layout + }, + setTitle(title: string) { + this.title = title + }, + setIsDark(isDark: boolean) { + this.isDark = isDark + if (this.isDark) { + document.documentElement.classList.add('dark') + document.documentElement.classList.remove('light') + } else { + document.documentElement.classList.add('light') + document.documentElement.classList.remove('dark') + } + this.setPrimaryLight() + }, + setCurrentSize(currentSize: ComponentSize) { + this.currentSize = currentSize + }, + setMobile(mobile: boolean) { + this.mobile = mobile + }, + setTheme(theme: ThemeTypes) { + this.theme = Object.assign(this.theme, theme) + }, + setCssVarTheme() { + for (const key in this.theme) { + setCssVar(`--${humpToUnderline(key)}`, this.theme[key]) + } + this.setPrimaryLight() + }, + setFooter(footer: boolean) { + this.footer = footer + }, + setPrimaryLight() { + if (this.theme.elColorPrimary) { + const elColorPrimary = this.theme.elColorPrimary + const color = this.isDark ? '#000000' : '#ffffff' + const lightList = [3, 5, 7, 8, 9] + lightList.forEach((v) => { + setCssVar(`--el-color-primary-light-${v}`, mix(color, elColorPrimary, v / 10)) + }) + setCssVar(`--el-color-primary-dark-2`, mix(color, elColorPrimary, 0.2)) + } + }, + setMenuTheme(color: string) { + const primaryColor = useCssVar('--el-color-primary', document.documentElement) + const isDarkColor = colorIsDark(color) + const theme: Recordable = { + // 左侧菜单边框颜色 + leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee', + // 左侧菜单背景颜色 + leftMenuBgColor: color, + // 左侧菜单浅色背景颜色 + leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color, + // 左侧菜单选中背景颜色 + leftMenuBgActiveColor: isDarkColor + ? 'var(--el-color-primary)' + : hexToRGB(unref(primaryColor), 0.1), + // 左侧菜单收起选中背景颜色 + leftMenuCollapseBgActiveColor: isDarkColor + ? 'var(--el-color-primary)' + : hexToRGB(unref(primaryColor), 0.1), + // 左侧菜单字体颜色 + leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333', + // 左侧菜单选中字体颜色 + leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)', + // logo字体颜色 + logoTitleTextColor: isDarkColor ? '#fff' : 'inherit', + // logo边框颜色 + logoBorderColor: isDarkColor ? color : '#eee' + } + this.setTheme(theme) + this.setCssVarTheme() + }, + setHeaderTheme(color: string) { + const isDarkColor = colorIsDark(color) + const textColor = isDarkColor ? '#fff' : 'inherit' + const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6' + const topToolBorderColor = isDarkColor ? color : '#eee' + setCssVar('--top-header-bg-color', color) + setCssVar('--top-header-text-color', textColor) + setCssVar('--top-header-hover-color', textHoverColor) + this.setTheme({ + topHeaderBgColor: color, + topHeaderTextColor: textColor, + topHeaderHoverColor: textHoverColor, + topToolBorderColor + }) + if (this.getLayout === 'top') { + this.setMenuTheme(color) + } + }, + initTheme() { + const isDark = useDark({ + valueDark: 'dark', + valueLight: 'light' + }) + isDark.value = this.getIsDark + } + }, + persist: true +}) + +export const useAppStoreWithOut = () => { + return useAppStore(store) +} diff --git a/src/store/modules/locale.ts b/src/store/modules/locale.ts new file mode 100644 index 000000000..8d2ba35df --- /dev/null +++ b/src/store/modules/locale.ts @@ -0,0 +1,59 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import en from 'element-plus/es/locale/lang/en' +import { useStorage } from '@/hooks/web/useStorage' +import { LocaleDropdownType } from '@/components/LocaleDropdown' + +const { getStorage, setStorage } = useStorage('localStorage') + +const elLocaleMap = { + 'zh-CN': zhCn, + en: en +} +interface LocaleState { + currentLocale: LocaleDropdownType + localeMap: LocaleDropdownType[] +} + +export const useLocaleStore = defineStore('locales', { + state: (): LocaleState => { + return { + currentLocale: { + lang: getStorage('lang') || 'zh-CN', + elLocale: elLocaleMap[getStorage('lang') || 'zh-CN'] + }, + // 多语言 + localeMap: [ + { + lang: 'zh-CN', + name: '简体中文' + }, + { + lang: 'en', + name: 'English' + } + ] + } + }, + getters: { + getCurrentLocale(): LocaleDropdownType { + return this.currentLocale + }, + getLocaleMap(): LocaleDropdownType[] { + return this.localeMap + } + }, + actions: { + setCurrentLocale(localeMap: LocaleDropdownType) { + // this.locale = Object.assign(this.locale, localeMap) + this.currentLocale.lang = localeMap?.lang + this.currentLocale.elLocale = elLocaleMap[localeMap?.lang] + setStorage('lang', localeMap?.lang) + } + } +}) + +export const useLocaleStoreWithOut = () => { + return useLocaleStore(store) +} diff --git a/src/store/modules/lock.ts b/src/store/modules/lock.ts new file mode 100644 index 000000000..70ff87f26 --- /dev/null +++ b/src/store/modules/lock.ts @@ -0,0 +1,48 @@ +import { defineStore } from 'pinia' +import { store } from '../index' + +interface lockInfo { + isLock?: boolean + password?: string +} + +interface LockState { + lockInfo: lockInfo +} + +export const useLockStore = defineStore('lock', { + state: (): LockState => { + return { + lockInfo: { + // isLock: false, // 是否锁定屏幕 + // password: '' // 锁屏密码 + } + } + }, + getters: { + getLockInfo(): lockInfo { + return this.lockInfo + } + }, + actions: { + setLockInfo(lockInfo: lockInfo) { + this.lockInfo = lockInfo + }, + resetLockInfo() { + this.lockInfo = {} + }, + unLock(password: string) { + if (this.lockInfo?.password === password) { + this.resetLockInfo() + return true + } else { + return false + } + } + }, + persist: true +}) + +export const useLockStoreWithOut = () => { + return useLockStore(store) +} diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts new file mode 100644 index 000000000..c9973067c --- /dev/null +++ b/src/store/modules/permission.ts @@ -0,0 +1,87 @@ +import { defineStore } from 'pinia' +import { asyncRouterMap, constantRouterMap } from '@/router' +import { + generateRoutesByFrontEnd, + generateRoutesByServer, + flatMultiLevelRoutes +} from '@/utils/routerHelper' +import { store } from '../index' +import { cloneDeep } from 'lodash-es' + +export interface PermissionState { + routers: AppRouteRecordRaw[] + addRouters: AppRouteRecordRaw[] + isAddRouters: boolean + menuTabRouters: AppRouteRecordRaw[] +} + +export const usePermissionStore = defineStore('permission', { + state: (): PermissionState => ({ + routers: [], + addRouters: [], + isAddRouters: false, + menuTabRouters: [] + }), + getters: { + getRouters(): AppRouteRecordRaw[] { + return this.routers + }, + getAddRouters(): AppRouteRecordRaw[] { + return flatMultiLevelRoutes(cloneDeep(this.addRouters)) + }, + getIsAddRouters(): boolean { + return this.isAddRouters + }, + getMenuTabRouters(): AppRouteRecordRaw[] { + return this.menuTabRouters + } + }, + actions: { + generateRoutes( + type: 'server' | 'frontEnd' | 'static', + routers?: AppCustomRouteRecordRaw[] | string[] + ): Promise { + return new Promise((resolve) => { + let routerMap: AppRouteRecordRaw[] = [] + if (type === 'server') { + // 模拟后端过滤菜单 + routerMap = generateRoutesByServer(routers as AppCustomRouteRecordRaw[]) + } else if (type === 'frontEnd') { + // 模拟前端过滤菜单 + routerMap = generateRoutesByFrontEnd(cloneDeep(asyncRouterMap), routers as string[]) + } else { + // 直接读取静态路由表 + routerMap = cloneDeep(asyncRouterMap) + } + // 动态路由,404一定要放到最后面 + this.addRouters = routerMap.concat([ + { + path: '/:path(.*)*', + redirect: '/404', + name: '404Page', + meta: { + hidden: true, + breadcrumb: false + } + } + ]) + // 渲染菜单的所有路由 + this.routers = cloneDeep(constantRouterMap).concat(routerMap) + resolve() + }) + }, + setIsAddRouters(state: boolean): void { + this.isAddRouters = state + }, + setMenuTabRouters(routers: AppRouteRecordRaw[]): void { + this.menuTabRouters = routers + } + }, + persist: { + paths: ['routers', 'addRouters', 'menuTabRouters'] + } +}) + +export const usePermissionStoreWithOut = () => { + return usePermissionStore(store) +} diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts new file mode 100644 index 000000000..d07a439bf --- /dev/null +++ b/src/store/modules/tagsView.ts @@ -0,0 +1,163 @@ +import router from '@/router' +import type { RouteLocationNormalizedLoaded } from 'vue-router' +import { getRawRoute } from '@/utils/routerHelper' +import { defineStore } from 'pinia' +import { store } from '../index' +import { findIndex } from '@/utils' +import { useUserStoreWithOut } from './user' + +export interface TagsViewState { + visitedViews: RouteLocationNormalizedLoaded[] + cachedViews: Set + selectedTag?: RouteLocationNormalizedLoaded +} + +export const useTagsViewStore = defineStore('tagsView', { + state: (): TagsViewState => ({ + visitedViews: [], + cachedViews: new Set(), + selectedTag: undefined + }), + getters: { + getVisitedViews(): RouteLocationNormalizedLoaded[] { + return this.visitedViews + }, + getCachedViews(): string[] { + return Array.from(this.cachedViews) + }, + getSelectedTag(): RouteLocationNormalizedLoaded | undefined { + return this.selectedTag + } + }, + actions: { + // 新增缓存和tag + addView(view: RouteLocationNormalizedLoaded): void { + this.addVisitedView(view) + this.addCachedView() + }, + // 新增tag + addVisitedView(view: RouteLocationNormalizedLoaded) { + if (this.visitedViews.some((v) => v.path === view.path)) return + if (view.meta?.noTagsView) return + this.visitedViews.push( + Object.assign({}, view, { + title: view.meta?.title || 'no-name' + }) + ) + }, + // 新增缓存 + addCachedView() { + const cacheMap: Set = new Set() + for (const v of this.visitedViews) { + const item = getRawRoute(v) + const needCache = !item?.meta?.noCache + if (!needCache) { + continue + } + const name = item.name as string + cacheMap.add(name) + } + if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString()) + return + this.cachedViews = cacheMap + }, + // 删除某个 + delView(view: RouteLocationNormalizedLoaded) { + this.delVisitedView(view) + this.addCachedView() + }, + // 删除tag + delVisitedView(view: RouteLocationNormalizedLoaded) { + for (const [i, v] of this.visitedViews.entries()) { + if (v.path === view.path) { + this.visitedViews.splice(i, 1) + break + } + } + }, + // 删除缓存 + delCachedView() { + const route = router.currentRoute.value + const index = findIndex(this.getCachedViews, (v) => v === route.name) + if (index > -1) { + this.cachedViews.delete(this.getCachedViews[index]) + } + }, + // 删除所有缓存和tag + delAllViews() { + this.delAllVisitedViews() + this.addCachedView() + }, + // 删除所有tag + delAllVisitedViews() { + const userStore = useUserStoreWithOut() + + // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) + this.visitedViews = userStore.getUserInfo + ? this.visitedViews.filter((tag) => tag?.meta?.affix) + : [] + }, + // 删除其它 + delOthersViews(view: RouteLocationNormalizedLoaded) { + this.delOthersVisitedViews(view) + this.addCachedView() + }, + // 删除其它tag + delOthersVisitedViews(view: RouteLocationNormalizedLoaded) { + this.visitedViews = this.visitedViews.filter((v) => { + return v?.meta?.affix || v.path === view.path + }) + }, + // 删除左侧 + delLeftViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i > index + }) + this.addCachedView() + } + }, + // 删除右侧 + delRightViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i < index + }) + this.addCachedView() + } + }, + updateVisitedView(view: RouteLocationNormalizedLoaded) { + for (let v of this.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + // 设置当前选中的tag + setSelectedTag(tag: RouteLocationNormalizedLoaded) { + this.selectedTag = tag + }, + setTitle(title: string, path?: string) { + for (const v of this.visitedViews) { + if (v.path === (path ?? this.selectedTag?.path)) { + v.meta.title = title + break + } + } + } + }, + persist: false +}) + +export const useTagsViewStoreWithOut = () => { + return useTagsViewStore(store) +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 000000000..1a9cf01d1 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,119 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { UserLoginType, UserType } from '@/api/login/types' +import { ElMessageBox } from 'element-plus' +import { useI18n } from '@/hooks/web/useI18n' +import { loginOutApi } from '@/api/login' +import { useTagsViewStore } from './tagsView' +import router from '@/router' + +interface UserState { + userInfo?: UserType + tokenKey: string + token: string + roleRouters?: string[] | AppCustomRouteRecordRaw[] + rememberMe: boolean + loginInfo?: UserLoginType + tenantId?: string + tenantEnable: boolean +} + +export const useUserStore = defineStore('user', { + state: (): UserState => { + return { + userInfo: undefined, + tokenKey: 'Authorization', + token: '', + roleRouters: undefined, + // 记住我 + rememberMe: true, + loginInfo: undefined, + tenantId: undefined, + tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE === 'true' + } + }, + getters: { + getTokenKey(): string { + return this.tokenKey + }, + getToken(): string { + return this.token + }, + getUserInfo(): UserType | undefined { + return this.userInfo + }, + getRoleRouters(): string[] | AppCustomRouteRecordRaw[] | undefined { + return this.roleRouters + }, + getRememberMe(): boolean { + return this.rememberMe + }, + getLoginInfo(): UserLoginType | undefined { + return this.loginInfo + }, + getTenantId(): string | undefined { + return this.tenantId + }, + getTenantEnable(): boolean { + return this.tenantEnable + } + }, + actions: { + setTokenKey(tokenKey: string) { + this.tokenKey = tokenKey + }, + setToken(token: string) { + this.token = token + }, + setUserInfo(userInfo?: UserType) { + this.userInfo = userInfo + }, + setRoleRouters(roleRouters: string[] | AppCustomRouteRecordRaw[]) { + this.roleRouters = roleRouters + }, + logoutConfirm() { + const { t } = useI18n() + ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + .then(async () => { + const res = await loginOutApi().catch(() => {}) + if (res) { + this.reset() + } + }) + .catch(() => {}) + }, + reset() { + const tagsViewStore = useTagsViewStore() + tagsViewStore.delAllViews() + this.setToken('') + this.setUserInfo(undefined) + this.setRoleRouters([]) + this.setTenantId(undefined) + router.replace('/login') + }, + logout() { + this.reset() + }, + setRememberMe(rememberMe: boolean) { + this.rememberMe = rememberMe + }, + setLoginInfo(loginInfo: UserLoginType | undefined) { + this.loginInfo = loginInfo + }, + setTenantId(tenantId?: string) { + this.tenantId = tenantId + }, + setTenantEnable(enable: boolean) { + this.tenantEnable = enable + } + }, + persist: true +}) + +export const useUserStoreWithOut = () => { + return useUserStore(store) +} diff --git a/src/styles/index.less b/src/styles/index.less new file mode 100644 index 000000000..6825d70ce --- /dev/null +++ b/src/styles/index.less @@ -0,0 +1,7 @@ +@import './var.css'; +@import 'element-plus/theme-chalk/dark/css-vars.css'; + +// 解决抽屉弹出时,body宽度变化的问题 +.el-popup-parent--hidden { + width: 100% !important; +} diff --git a/src/styles/var.css b/src/styles/var.css new file mode 100644 index 000000000..fb869ec93 --- /dev/null +++ b/src/styles/var.css @@ -0,0 +1,69 @@ +:root { + --login-bg-color: #293146; + + /* left menu start */ + --left-menu-max-width: 200px; + + --left-menu-min-width: 64px; + + --left-menu-bg-color: #001529; + + --left-menu-bg-light-color: #0f2438; + + --left-menu-bg-active-color: var(--el-color-primary); + + --left-menu-text-color: #bfcbd9; + + --left-menu-text-active-color: #fff; + + --left-menu-collapse-bg-active-color: var(--el-color-primary); + /* left menu end */ + + /* logo start */ + --logo-height: 50px; + + --logo-title-text-color: #fff; + /* logo end */ + + /* header start */ + --top-header-bg-color: '#fff'; + + --top-header-text-color: 'inherit'; + + --top-header-hover-color: #f6f6f6; + + --top-tool-height: var(--logo-height); + + --top-tool-p-x: 0; + + --tags-view-height: 35px; + /* header start */ + + /* tab menu start */ + --tab-menu-max-width: 80px; + + --tab-menu-min-width: 30px; + + --tab-menu-collapse-height: 36px; + /* tab menu end */ + + --app-content-padding: 20px; + + --app-content-bg-color: #f5f7f9; + + --app-footer-height: 50px; + + --transition-time-02: 0.2s; +} + +.dark { + --app-content-bg-color: var(--el-bg-color); +} + +*, +:after, +:before { + margin: 0; + padding: 0; + box-sizing: border-box; +} diff --git a/src/styles/variables.module.less b/src/styles/variables.module.less new file mode 100644 index 000000000..a77326903 --- /dev/null +++ b/src/styles/variables.module.less @@ -0,0 +1,10 @@ +// 命名空间 +@adminNamespace: v; +// el命名空间 +@elNamespace: el; + +// 导出变量 +:export { + namespace: @adminNamespace; + elNamespace: @elNamespace; +} diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 000000000..c8d423320 --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,77 @@ +import { useStorage } from '@/hooks/web/useStorage' +import { TokenType } from '@/api/login/types' +import { decrypt, encrypt } from '@/utils/jsencrypt' + +const CACHE_KEY = { + LoginForm: 'LOGIN_FORM', + TenantId: 'TENANT_ID' +} + +const { setStorage, getStorage, removeStorage } = useStorage() + +const AccessTokenKey = 'ACCESS_TOKEN' +const RefreshTokenKey = 'REFRESH_TOKEN' + +// 获取token +export const getAccessToken = () => { + // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错 + const accessToken = wsCache.get(AccessTokenKey) + return accessToken ? accessToken : wsCache.get('ACCESS_TOKEN') +} + +// 刷新token +export const getRefreshToken = () => { + return getStorage(RefreshTokenKey) +} + +// 设置token +export const setToken = (token: TokenType) => { + wsCache.set(RefreshTokenKey, token.refreshToken) + wsCache.set(AccessTokenKey, token.accessToken) +} + +// 删除token +export const removeToken = () => { + removeStorage(AccessTokenKey) + removeStorage(RefreshTokenKey) +} + +/** 格式化token(jwt格式) */ +export const formatToken = (token: string): string => { + return 'Bearer ' + token +} +// ========== 账号相关 ========== + +export type LoginFormType = { + tenantName: string + username: string + password: string + rememberMe: boolean +} + +export const getLoginForm = () => { + const loginForm: LoginFormType = wsCache.get(CACHE_KEY.LoginForm) + if (loginForm) { + loginForm.password = decrypt(loginForm.password) as string + } + return loginForm +} + +export const setLoginForm = (loginForm: LoginFormType) => { + loginForm.password = encrypt(loginForm.password) as string + setStorage(CACHE_KEY.LoginForm, loginForm) +} + +export const removeLoginForm = () => { + wsCache.delete(CACHE_KEY.LoginForm) +} + +// ========== 租户相关 ========== + +export const getTenantId = () => { + return getStorage(CACHE_KEY.TenantId) +} + +export const setTenantId = (username: string) => { + wsCache.set(CACHE_KEY.TenantId, username) +} diff --git a/src/utils/color.ts b/src/utils/color.ts new file mode 100644 index 000000000..387ffc672 --- /dev/null +++ b/src/utils/color.ts @@ -0,0 +1,172 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export const isHexColor = (color: string) => { + const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/ + return reg.test(color) +} + +/** + * RGB 颜色值转换为 十六进制颜色值. + * r, g, 和 b 需要在 [0, 255] 范围内 + * + * @return String 类似#ff00ff + * @param r + * @param g + * @param b + */ +export const rgbToHex = (r: number, g: number, b: number) => { + // tslint:disable-next-line:no-bitwise + const hex = ((r << 16) | (g << 8) | b).toString(16) + return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex +} + +/** + * Transform a HEX color to its RGB representation + * @param {string} hex The color to transform + * @returns The RGB representation of the passed color + */ +export const hexToRGB = (hex: string, opacity?: number) => { + let sHex = hex.toLowerCase() + if (isHexColor(hex)) { + if (sHex.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)) + } + sHex = sColorNew + } + const sColorChange: number[] = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))) + } + return opacity + ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')' + : 'RGB(' + sColorChange.join(',') + ')' + } + return sHex +} + +export const colorIsDark = (color: string) => { + if (!isHexColor(color)) return + const [r, g, b] = hexToRGB(color) + .replace(/(?:\(|\)|rgb|RGB)*/g, '') + .split(',') + .map((item) => Number(item)) + return r * 0.299 + g * 0.578 + b * 0.114 < 192 +} + +/** + * Darkens a HEX color given the passed percentage + * @param {string} color The color to process + * @param {number} amount The amount to change the color by + * @returns {string} The HEX representation of the processed color + */ +export const darken = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount + )}${subtractLight(color.substring(4, 6), amount)}` +} + +/** + * Lightens a 6 char HEX color according to the passed percentage + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed color represented as HEX + */ +export const lighten = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount + )}${addLight(color.substring(4, 6), amount)}` +} + +/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ +/** + * Sums the passed percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const addLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) + amount + const c = cc > 255 ? 255 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +/** + * Calculates luminance of an rgb color + * @param {number} r red + * @param {number} g green + * @param {number} b blue + */ +const luminanace = (r: number, g: number, b: number) => { + const a = [r, g, b].map((v) => { + v /= 255 + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4) + }) + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722 +} + +/** + * Calculates contrast between two rgb colors + * @param {string} rgb1 rgb color 1 + * @param {string} rgb2 rgb color 2 + */ +const contrast = (rgb1: string[], rgb2: number[]) => { + return ( + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ) +} + +/** + * Determines what the best text color is (black or white) based con the contrast with the background + * @param hexColor - Last selected color by the user + */ +export const calculateBestTextColor = (hexColor: string) => { + const rgbColor = hexToRGB(hexColor.substring(1)) + const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]) + + return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF' +} + +/** + * Subtracts the indicated percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const subtractLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) - amount + const c = cc < 0 ? 0 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +/** + * Mixes two colors. + * + * @param {string} color1 - The first color, should be a 6-digit hexadecimal color code starting with `#`. + * @param {string} color2 - The second color, should be a 6-digit hexadecimal color code starting with `#`. + * @param {number} [weight=0.5] - The weight of color1 in the mix, should be a number between 0 and 1, where 0 represents 100% of color2, and 1 represents 100% of color1. + * @returns {string} The mixed color, a 6-digit hexadecimal color code starting with `#`. + */ +export const mix = (color1: string, color2: string, weight: number = 0.5): string => { + let color = '#' + for (let i = 0; i <= 2; i++) { + const c1 = parseInt(color1.substring(1 + i * 2, 3 + i * 2), 16) + const c2 = parseInt(color2.substring(1 + i * 2, 3 + i * 2), 16) + const c = Math.round(c1 * weight + c2 * (1 - weight)) + color += c.toString(16).padStart(2, '0') + } + return color +} diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 000000000..36b87e34a --- /dev/null +++ b/src/utils/dateUtil.ts @@ -0,0 +1,17 @@ +/** + * Independent time operation tool to facilitate subsequent switch to dayjs + */ +import dayjs from 'dayjs' + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' +const DATE_FORMAT = 'YYYY-MM-DD' + +export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string { + return dayjs(date).format(format) +} + +export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string { + return dayjs(date).format(format) +} + +export const dateUtil = dayjs diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts new file mode 100644 index 000000000..dbc1989cb --- /dev/null +++ b/src/utils/domUtils.ts @@ -0,0 +1,289 @@ +import { isServer } from './is' +const ieVersion = isServer ? 0 : Number((document as any).documentMode) +const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g +const MOZ_HACK_REGEXP = /^moz([A-Z])/ + +export interface ViewportOffsetResult { + left: number + top: number + right: number + bottom: number + rightIncludeBody: number + bottomIncludeBody: number +} + +/* istanbul ignore next */ +const trim = function (string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') +} + +/* istanbul ignore next */ +const camelCase = function (name: string) { + return name + .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) { + return offset ? letter.toUpperCase() : letter + }) + .replace(MOZ_HACK_REGEXP, 'Moz$1') +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false + if (cls.indexOf(' ') !== -1) { + throw new Error('className should not contain space.') + } + if (el.classList) { + return el.classList.contains(cls) + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return + let curClass = el.className + const classes = (cls || '').split(' ') + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.add(clsName) + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName + } + } + if (!el.classList) { + el.className = curClass + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return + const classes = cls.split(' ') + let curClass = ' ' + el.className + ' ' + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.remove(clsName) + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' ') + } + } + if (!el.classList) { + el.className = trim(curClass) + } +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0 + } + return element.getBoundingClientRect() +} + +/** + * 获取当前元素的left、top偏移 + * left:元素最左侧距离文档左侧的距离 + * top:元素最顶端距离文档顶端的距离 + * right:元素最右侧距离文档右侧的距离 + * bottom:元素最底端距离文档底端的距离 + * rightIncludeBody:元素最左侧距离文档右侧的距离 + * bottomIncludeBody:元素最底端距离文档最底部的距离 + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement + + const docScrollLeft = doc.scrollLeft + const docScrollTop = doc.scrollTop + const docClientLeft = doc.clientLeft + const docClientTop = doc.clientTop + + const pageXOffset = window.pageXOffset + const pageYOffset = window.pageYOffset + + const box = getBoundingClientRect(element) + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0) + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0) + const offsetLeft = retLeft + pageXOffset + const offsetTop = rectTop + pageYOffset + + const left = offsetLeft - scrollLeft + const top = offsetTop - scrollTop + + const clientWidth = window.document.documentElement.clientWidth + const clientHeight = window.document.documentElement.clientHeight + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top + } +} + +/* istanbul ignore next */ +export const on = function ( + element: HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const off = function ( + element: HTMLElement | Document | Window, + event: string, + handler: any +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const once = function (el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + // @ts-ignore + fn.apply(this, args) + } + off(el, event, listener) + } + on(el, event, listener) +} + +/* istanbul ignore next */ +export const getStyle = + ieVersion < 9 + ? function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'styleFloat' + } + try { + switch (styleName) { + case 'opacity': + try { + return element.filters.item('alpha').opacity / 100 + } catch (e) { + return 1.0 + } + default: + return element.style[styleName] || element.currentStyle + ? element.currentStyle[styleName] + : null + } + } catch (e) { + return element.style[styleName] + } + } + : function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'cssFloat' + } + try { + const computed = (document as any).defaultView.getComputedStyle(element, '') + return element.style[styleName] || computed ? computed[styleName] : null + } catch (e) { + return element.style[styleName] + } + } + +/* istanbul ignore next */ +export function setStyle(element: Element | any, styleName: any, value: any) { + if (!element || !styleName) return + + if (typeof styleName === 'object') { + for (const prop in styleName) { + if (Object.prototype.hasOwnProperty.call(styleName, prop)) { + setStyle(element, prop, styleName[prop]) + } + } + } else { + styleName = camelCase(styleName) + if (styleName === 'opacity' && ieVersion < 9) { + element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')' + } else { + element.style[styleName] = value + } + } +} + +/* istanbul ignore next */ +export const isScroll = (el: Element, vertical: any) => { + if (isServer) return + + const determinedDirection = vertical !== null || vertical !== undefined + const overflow = determinedDirection + ? vertical + ? getStyle(el, 'overflow-y') + : getStyle(el, 'overflow-x') + : getStyle(el, 'overflow') + + return overflow.match(/(scroll|auto)/) +} + +/* istanbul ignore next */ +export const getScrollContainer = (el: Element, vertical?: any) => { + if (isServer) return + + let parent: any = el + while (parent) { + if ([window, document, document.documentElement].includes(parent)) { + return window + } + if (isScroll(parent, vertical)) { + return parent + } + parent = parent.parentNode + } + + return parent +} + +/* istanbul ignore next */ +export const isInContainer = (el: Element, container: any) => { + if (isServer || !el || !container) return false + + const elRect = el.getBoundingClientRect() + let containerRect + + if ([window, document, document.documentElement, null, undefined].includes(container)) { + containerRect = { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0 + } + } else { + containerRect = container.getBoundingClientRect() + } + + return ( + elRect.top < containerRect.bottom && + elRect.bottom > containerRect.top && + elRect.right > containerRect.left && + elRect.left < containerRect.right + ) +} diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts new file mode 100644 index 000000000..a5f819c3a --- /dev/null +++ b/src/utils/encrypt.ts @@ -0,0 +1,39 @@ +/** + * 加密工具函数 + */ + +/** + * Base64加密 + * @param str 需要加密的字符串 + * @returns 加密后的字符串 + */ +export function encryptBase64(str: string): string { + return window.btoa(encodeURIComponent(str)) +} + +/** + * Base64解密 + * @param str 需要解密的字符串 + * @returns 解密后的字符串 + */ +export function decryptBase64(str: string): string { + return decodeURIComponent(window.atob(str)) +} + +/** + * 简单加密(仅用于演示,生产环境应使用更安全的加密方式) + * @param str 需要加密的字符串 + * @returns 加密后的字符串 + */ +export function encrypt(str: string): string { + return encryptBase64(str) +} + +/** + * 简单解密(仅用于演示,生产环境应使用更安全的解密方式) + * @param str 需要解密的字符串 + * @returns 解密后的字符串 + */ +export function decrypt(str: string): string { + return decryptBase64(str) +} \ No newline at end of file diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 000000000..d91b67917 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,136 @@ +/** + * + * @param component 需要注册的组件 + * @param alias 组件别名 + * @returns any + */ +export const withInstall = (component: T, alias?: string) => { + const comp = component as any + comp.install = (app: any) => { + app.component(comp.name || comp.displayName, component) + if (alias) { + app.config.globalProperties[alias] = component + } + } + return component as T & Plugin +} + +/** + * @param str 需要转下划线的驼峰字符串 + * @returns 字符串下划线 + */ +export const humpToUnderline = (str: string): string => { + return str.replace(/([A-Z])/g, '-$1').toLowerCase() +} + +/** + * @param str 需要转驼峰的下划线字符串 + * @returns 字符串驼峰 + */ +export const underlineToHump = (str: string): string => { + if (!str) return '' + return str.replace(/\-(\w)/g, (_, letter: string) => { + return letter.toUpperCase() + }) +} + +/** + * 驼峰转横杠 + */ +export const humpToDash = (str: string): string => { + return str.replace(/([A-Z])/g, '-$1').toLowerCase() +} + +export const setCssVar = (prop: string, val: any, dom = document.documentElement) => { + dom.style.setProperty(prop, val) +} + +export const getCssVar = (prop: string, dom = document.documentElement) => { + return getComputedStyle(dom).getPropertyValue(prop) +} + +/** + * 查找数组对象的某个下标 + * @param {Array} ary 查找的数组 + * @param {Functon} fn 判断的方法 + */ +export const findIndex = (ary: Array, fn: Fn): number => { + if (ary.findIndex) { + return ary.findIndex(fn) + } + let index = -1 + ary.some((item: T, i: number, ary: Array) => { + const ret: T = fn(item, i, ary) + if (ret) { + index = i + return ret + } + }) + return index +} + +export const trim = (str: string) => { + return str.replace(/(^\s*)|(\s*$)/g, '') +} + +/** + * @param {Date | number | string} time 需要转换的时间 + * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss + */ +export function formatTime(time: Date | number | string, fmt: string) { + if (!time) return '' + else { + const date = new Date(time) + const o = { + 'M+': date.getMonth() + 1, + 'd+': date.getDate(), + 'H+': date.getHours(), + 'm+': date.getMinutes(), + 's+': date.getSeconds(), + 'q+': Math.floor((date.getMonth() + 3) / 3), + S: date.getMilliseconds() + } + if (/(y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) + } + for (const k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { + fmt = fmt.replace( + RegExp.$1, + RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length) + ) + } + } + return fmt + } +} + +/** + * 生成随机字符串 + */ +export function toAnyString() { + const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => { + const r: number = (Math.random() * 16) | 0 + const v: number = c === 'x' ? r : (r & 0x3) | 0x8 + return v.toString() + }) + return str +} + +/** + * 首字母大写 + */ +export function firstUpperCase(str: string) { + return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase()) +} + +/** + * 把对象转为formData + */ +export function objToFormData(obj: Recordable) { + const formData = new FormData() + Object.keys(obj).forEach((key) => { + formData.append(key, obj[key]) + }) + return formData +} diff --git a/src/utils/is.ts b/src/utils/is.ts new file mode 100644 index 000000000..16514205a --- /dev/null +++ b/src/utils/is.ts @@ -0,0 +1,117 @@ +// copy to vben-admin + +const toString = Object.prototype.toString + +export const is = (val: unknown, type: string) => { + return toString.call(val) === `[object ${type}]` +} + +export const isDef = (val?: T): val is T => { + return typeof val !== 'undefined' +} + +export const isUnDef = (val?: T): val is T => { + return !isDef(val) +} + +export const isObject = (val: any): val is Record => { + return val !== null && is(val, 'Object') +} + +export const isEmpty = (val: T): val is T => { + if (isArray(val) || isString(val)) { + return val.length === 0 + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0 + } + + if (isObject(val)) { + return Object.keys(val).length === 0 + } + + return false +} + +export const isDate = (val: unknown): val is Date => { + return is(val, 'Date') +} + +export const isNull = (val: unknown): val is null => { + return val === null +} + +export const isNullAndUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) && isNull(val) +} + +export const isNullOrUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) || isNull(val) +} + +export const isNumber = (val: unknown): val is number => { + return is(val, 'Number') +} + +export const isPromise = (val: unknown): val is Promise => { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) +} + +export const isString = (val: unknown): val is string => { + return is(val, 'String') +} + +export const isFunction = (val: unknown): val is Function => { + return typeof val === 'function' +} + +export const isBoolean = (val: unknown): val is boolean => { + return is(val, 'Boolean') +} + +export const isRegExp = (val: unknown): val is RegExp => { + return is(val, 'RegExp') +} + +export const isArray = (val: any): val is Array => { + return val && Array.isArray(val) +} + +export const isWindow = (val: any): val is Window => { + return typeof window !== 'undefined' && is(val, 'Window') +} + +export const isElement = (val: unknown): val is Element => { + return isObject(val) && !!val.tagName +} + +export const isMap = (val: unknown): val is Map => { + return is(val, 'Map') +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer + +export const isUrl = (path: string): boolean => { + try { + new URL(path) + return true + } catch (_error) { + return false + } +} + +export const isDark = (): boolean => { + return window.matchMedia('(prefers-color-scheme: dark)').matches +} + +// 是否是图片链接 +export const isImgPath = (path: string): boolean => { + return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path) +} + +export const isEmptyVal = (val: any): boolean => { + return val === '' || val === null || val === undefined +} diff --git a/src/utils/jsencrypt.ts b/src/utils/jsencrypt.ts new file mode 100644 index 000000000..63cd3a8dc --- /dev/null +++ b/src/utils/jsencrypt.ts @@ -0,0 +1,25 @@ +// 由于缺少jsencrypt依赖,使用简单的Base64编码/解码作为临时替代方案 + +// 加密 - 使用Base64编码 +export const encrypt = (txt: string) => { + if (!txt) return '' + try { + // 使用内置的btoa函数进行Base64编码 + return window.btoa(encodeURIComponent(txt)) + } catch (e) { + console.error('加密失败', e) + return '' + } +} + +// 解密 - 使用Base64解码 +export const decrypt = (txt: string) => { + if (!txt) return '' + try { + // 使用内置的atob函数进行Base64解码 + return decodeURIComponent(window.atob(txt)) + } catch (e) { + console.error('解密失败', e) + return '' + } +} diff --git a/src/utils/propTypes.ts b/src/utils/propTypes.ts new file mode 100644 index 000000000..863f55cc1 --- /dev/null +++ b/src/utils/propTypes.ts @@ -0,0 +1,24 @@ +import { VueTypeValidableDef, VueTypesInterface, createTypes, toValidableType } from 'vue-types' +import { CSSProperties } from 'vue' + +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef +} +const newPropTypes = createTypes({ + func: undefined, + bool: undefined, + string: undefined, + number: undefined, + object: undefined, + integer: undefined +}) as PropTypes + +class propTypes extends newPropTypes { + static get style() { + return toValidableType('style', { + type: [String, Object] + }) + } +} + +export { propTypes } diff --git a/src/utils/routerHelper.ts b/src/utils/routerHelper.ts new file mode 100644 index 000000000..b4e7548ff --- /dev/null +++ b/src/utils/routerHelper.ts @@ -0,0 +1,197 @@ +import { createRouter, createWebHashHistory } from 'vue-router' +import type { + Router, + RouteLocationNormalized, + RouteRecordNormalized, + RouteRecordRaw +} from 'vue-router' +import { isUrl } from '@/utils/is' +import { omit, cloneDeep } from 'lodash-es' + +const modules = import.meta.glob('../views/**/*.{vue,tsx}') + +/* Layout */ +export const Layout = () => import('@/layout/Layout.vue') + +export const getParentLayout = () => { + return () => + new Promise((resolve) => { + resolve({ + name: 'ParentLayout' + }) + }) +} + +export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => { + if (!route) return route + const { matched, ...opt } = route + return { + ...opt, + matched: (matched + ? matched.map((item) => ({ + meta: item.meta, + name: item.name, + path: item.path + })) + : undefined) as RouteRecordNormalized[] + } +} + +// 前端控制路由生成 +export const generateRoutesByFrontEnd = ( + routes: AppRouteRecordRaw[], + keys: string[], + basePath = '/' +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + + for (const route of routes) { + const meta = route.meta ?? {} + // skip some route + if (meta.hidden && !meta.canTo) { + continue + } + + let data: Nullable = null + + let onlyOneChild: Nullable = null + if (route.children && route.children.length === 1 && !meta.alwaysShow) { + onlyOneChild = ( + isUrl(route.children[0].path) + ? route.children[0].path + : pathResolve(pathResolve(basePath, route.path), route.children[0].path) + ) as string + } + + // 开发者可以根据实际情况进行扩展 + for (const item of keys) { + // 通过路径去匹配 + if (isUrl(item) && (onlyOneChild === item || route.path === item)) { + data = Object.assign({}, route) + } else { + const routePath = (onlyOneChild ?? pathResolve(basePath, route.path)).trim() + if (routePath === item || meta.followRoute === item) { + data = Object.assign({}, route) + } + } + } + + // recursive child routes + if (route.children && data) { + data.children = generateRoutesByFrontEnd( + route.children, + keys, + pathResolve(basePath, data.path) + ) + } + if (data) { + res.push(data as AppRouteRecordRaw) + } + } + return res +} + +// 后端控制路由生成 +export const generateRoutesByServer = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + + for (const route of routes) { + const data: AppRouteRecordRaw = { + path: route.path, + name: route.name, + redirect: route.redirect, + meta: route.meta + } + if (route.component) { + const comModule = modules[`../${route.component}.vue`] || modules[`../${route.component}.tsx`] + const component = route.component as string + if (!comModule && !component.includes('#')) { + console.error(`未找到${route.component}.vue文件或${route.component}.tsx文件,请创建`) + } else { + // 动态加载路由文件,可根据实际情况进行自定义逻辑 + data.component = + component === '#' ? Layout : component.includes('##') ? getParentLayout() : comModule + } + } + // recursive child routes + if (route.children) { + data.children = generateRoutesByServer(route.children) + } + res.push(data as AppRouteRecordRaw) + } + return res +} + +export const pathResolve = (parentPath: string, path: string) => { + if (isUrl(path)) return path + const childPath = path.startsWith('/') || !path ? path : `/${path}` + return `${parentPath}${childPath}`.replace(/\/\//g, '/').trim() +} + +// 路由降级 +export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => { + const modules: AppRouteRecordRaw[] = cloneDeep(routes) + for (let index = 0; index < modules.length; index++) { + const route = modules[index] + if (!isMultipleRoute(route)) { + continue + } + promoteRouteLevel(route) + } + return modules +} + +// 层级是否大于2 +const isMultipleRoute = (route: AppRouteRecordRaw) => { + if (!route || !Reflect.has(route, 'children') || !route.children?.length) { + return false + } + + const children = route.children + + let flag = false + for (let index = 0; index < children.length; index++) { + const child = children[index] + if (child.children?.length) { + flag = true + break + } + } + return flag +} + +// 生成二级路由 +const promoteRouteLevel = (route: AppRouteRecordRaw) => { + let router: Router | null = createRouter({ + routes: [route as RouteRecordRaw], + history: createWebHashHistory() + }) + + const routes = router.getRoutes() + addToChildren(routes, route.children || [], route) + router = null + + route.children = route.children?.map((item) => omit(item, 'children')) +} + +// 添加所有子菜单 +const addToChildren = ( + routes: RouteRecordNormalized[], + children: AppRouteRecordRaw[], + routeModule: AppRouteRecordRaw +) => { + for (let index = 0; index < children.length; index++) { + const child = children[index] + const route = routes.find((item) => item.name === child.name) + if (!route) { + continue + } + routeModule.children = routeModule.children || [] + if (!routeModule.children.find((item) => item.name === route.name)) { + routeModule.children?.push(route as unknown as AppRouteRecordRaw) + } + if (child.children?.length) { + addToChildren(routes, child.children, routeModule) + } + } +} diff --git a/src/utils/tree.ts b/src/utils/tree.ts new file mode 100644 index 000000000..fe0207d52 --- /dev/null +++ b/src/utils/tree.ts @@ -0,0 +1,207 @@ +interface TreeHelperConfig { + id: string + children: string + pid: string +} +const DEFAULT_CONFIG: TreeHelperConfig = { + id: 'id', + children: 'children', + pid: 'pid' +} + +const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config) + +// tree from list +export const listToTree = (list: any[], config: Partial = {}): T[] => { + const conf = getConfig(config) as TreeHelperConfig + const nodeMap = new Map() + const result: T[] = [] + const { id, children, pid } = conf + + for (const node of list) { + node[children] = node[children] || [] + nodeMap.set(node[id], node) + } + for (const node of list) { + const parent = nodeMap.get(node[pid]) + ;(parent ? parent.children : result).push(node) + } + return result +} + +export const treeToList = (tree: any, config: Partial = {}): T => { + config = getConfig(config) + const { children } = config + const result: any = [...tree] + for (let i = 0; i < result.length; i++) { + if (!result[i][children!]) continue + result.splice(i + 1, 0, ...result[i][children!]) + } + return result +} + +export const findNode = ( + tree: any, + func: Fn, + config: Partial = {} +): T | null => { + config = getConfig(config) + const { children } = config + const list = [...tree] + for (const node of list) { + if (func(node)) return node + node[children!] && list.push(...node[children!]) + } + return null +} + +export const findNodeAll = ( + tree: any, + func: Fn, + config: Partial = {} +): T[] => { + config = getConfig(config) + const { children } = config + const list = [...tree] + const result: T[] = [] + for (const node of list) { + func(node) && result.push(node) + node[children!] && list.push(...node[children!]) + } + return result +} + +export const findPath = ( + tree: any, + func: Fn, + config: Partial = {} +): T | T[] | null => { + config = getConfig(config) + const path: T[] = [] + const list = [...tree] + const visitedSet = new Set() + const { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + if (func(node)) { + return path + } + } + } + return null +} + +export const findPathAll = (tree: any, func: Fn, config: Partial = {}) => { + config = getConfig(config) + const path: any[] = [] + const list = [...tree] + const result: any[] = [] + const visitedSet = new Set(), + { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + func(node) && result.push([...path]) + } + } + return result +} + +export const filter = ( + tree: T[], + func: (n: T) => boolean, + config: Partial = {} +): T[] => { + config = getConfig(config) + const children = config.children as string + function listFilter(list: T[]) { + return list + .map((node: any) => ({ ...node })) + .filter((node) => { + node[children] = node[children] && listFilter(node[children]) + return func(node) || (node[children] && node[children].length) + }) + } + return listFilter(tree) +} + +export const forEach = ( + tree: T[], + func: (n: T) => any, + config: Partial = {} +): void => { + config = getConfig(config) + const list: any[] = [...tree] + const { children } = config + for (let i = 0; i < list.length; i++) { + // func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿 + if (func(list[i])) { + return + } + children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]) + } +} + +/** + * @description: Extract tree specified structure + */ +export const treeMap = ( + treeData: T[], + opt: { children?: string; conversion: Fn } +): T[] => { + return treeData.map((item) => treeMapEach(item, opt)) +} + +/** + * @description: Extract tree specified structure + */ +export const treeMapEach = ( + data: any, + { children = 'children', conversion }: { children?: string; conversion: Fn } +) => { + const haveChildren = Array.isArray(data[children]) && data[children].length > 0 + const conversionData = conversion(data) || {} + if (haveChildren) { + return { + ...conversionData, + [children]: data[children].map((i: number) => + treeMapEach(i, { + children, + conversion + }) + ) + } + } else { + return { + ...conversionData + } + } +} + +/** + * 递归遍历树结构 + * @param treeDatas 树 + * @param callBack 回调 + * @param parentNode 父节点 + */ +export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { + treeDatas.forEach((element) => { + const newNode = callBack(element, parentNode) || element + if (element.children) { + eachTree(element.children, callBack, newNode) + } + }) +} diff --git a/src/utils/tsxHelper.ts b/src/utils/tsxHelper.ts new file mode 100644 index 000000000..6087fa30d --- /dev/null +++ b/src/utils/tsxHelper.ts @@ -0,0 +1,16 @@ +import { Slots } from 'vue' +import { isFunction } from '@/utils/is' + +export const getSlot = (slots: Slots, slot = 'default', data?: Recordable) => { + // Reflect.has 判断一个对象是否存在某个属性 + if (!slots || !Reflect.has(slots, slot)) { + return null + } + if (!isFunction(slots[slot])) { + console.error(`${slot} is not a function!`) + return null + } + const slotFn = slots[slot] + if (!slotFn) return null + return slotFn(data) +} diff --git a/src/views/Authorization/Department/Department.vue b/src/views/Authorization/Department/Department.vue new file mode 100644 index 000000000..c88970504 --- /dev/null +++ b/src/views/Authorization/Department/Department.vue @@ -0,0 +1,341 @@ + + + diff --git a/src/views/Authorization/Department/components/Detail.vue b/src/views/Authorization/Department/components/Detail.vue new file mode 100644 index 000000000..8262b9502 --- /dev/null +++ b/src/views/Authorization/Department/components/Detail.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Authorization/Department/components/Write.vue b/src/views/Authorization/Department/components/Write.vue new file mode 100644 index 000000000..2c3c5274b --- /dev/null +++ b/src/views/Authorization/Department/components/Write.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/views/Authorization/Menu/Menu.vue b/src/views/Authorization/Menu/Menu.vue new file mode 100644 index 000000000..1ea4fb3a8 --- /dev/null +++ b/src/views/Authorization/Menu/Menu.vue @@ -0,0 +1,212 @@ + + + diff --git a/src/views/Authorization/Menu/components/AddButtonPermission.vue b/src/views/Authorization/Menu/components/AddButtonPermission.vue new file mode 100644 index 000000000..32cb3c30f --- /dev/null +++ b/src/views/Authorization/Menu/components/AddButtonPermission.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/views/Authorization/Menu/components/Detail.vue b/src/views/Authorization/Menu/components/Detail.vue new file mode 100644 index 000000000..54b2cad9e --- /dev/null +++ b/src/views/Authorization/Menu/components/Detail.vue @@ -0,0 +1,173 @@ + + + diff --git a/src/views/Authorization/Menu/components/Write.vue b/src/views/Authorization/Menu/components/Write.vue new file mode 100644 index 000000000..2da8b6707 --- /dev/null +++ b/src/views/Authorization/Menu/components/Write.vue @@ -0,0 +1,409 @@ + + + diff --git a/src/views/Authorization/Role/Role.vue b/src/views/Authorization/Role/Role.vue new file mode 100644 index 000000000..4b67c3fe7 --- /dev/null +++ b/src/views/Authorization/Role/Role.vue @@ -0,0 +1,173 @@ + + + diff --git a/src/views/Authorization/Role/components/Detail.vue b/src/views/Authorization/Role/components/Detail.vue new file mode 100644 index 000000000..97c1b57d5 --- /dev/null +++ b/src/views/Authorization/Role/components/Detail.vue @@ -0,0 +1,106 @@ + + + diff --git a/src/views/Authorization/Role/components/Write.vue b/src/views/Authorization/Role/components/Write.vue new file mode 100644 index 000000000..0169427dd --- /dev/null +++ b/src/views/Authorization/Role/components/Write.vue @@ -0,0 +1,181 @@ + + + diff --git a/src/views/Authorization/User/User.vue b/src/views/Authorization/User/User.vue new file mode 100644 index 000000000..12ad2e206 --- /dev/null +++ b/src/views/Authorization/User/User.vue @@ -0,0 +1,384 @@ + + + diff --git a/src/views/Authorization/User/components/Detail.vue b/src/views/Authorization/User/components/Detail.vue new file mode 100644 index 000000000..81dd5ee44 --- /dev/null +++ b/src/views/Authorization/User/components/Detail.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Authorization/User/components/Write.vue b/src/views/Authorization/User/components/Write.vue new file mode 100644 index 000000000..ec60c8a99 --- /dev/null +++ b/src/views/Authorization/User/components/Write.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/views/Components/Avatars.vue b/src/views/Components/Avatars.vue new file mode 100644 index 000000000..430c7587f --- /dev/null +++ b/src/views/Components/Avatars.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/views/Components/CountTo.vue b/src/views/Components/CountTo.vue new file mode 100644 index 000000000..a547e8eab --- /dev/null +++ b/src/views/Components/CountTo.vue @@ -0,0 +1,100 @@ + + + diff --git a/src/views/Components/Descriptions.vue b/src/views/Components/Descriptions.vue new file mode 100644 index 000000000..4b96bf684 --- /dev/null +++ b/src/views/Components/Descriptions.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/src/views/Components/Dialog.vue b/src/views/Components/Dialog.vue new file mode 100644 index 000000000..33726e439 --- /dev/null +++ b/src/views/Components/Dialog.vue @@ -0,0 +1,165 @@ + + + diff --git a/src/views/Components/Echart.vue b/src/views/Components/Echart.vue new file mode 100644 index 000000000..683d6b4d1 --- /dev/null +++ b/src/views/Components/Echart.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/views/Components/Editor/CodeEditor.vue b/src/views/Components/Editor/CodeEditor.vue new file mode 100644 index 000000000..db80bb03c --- /dev/null +++ b/src/views/Components/Editor/CodeEditor.vue @@ -0,0 +1,23 @@ + + diff --git a/src/views/Components/Editor/Editor.vue b/src/views/Components/Editor/Editor.vue new file mode 100644 index 000000000..9dde431fb --- /dev/null +++ b/src/views/Components/Editor/Editor.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/views/Components/Editor/JsonEditor.vue b/src/views/Components/Editor/JsonEditor.vue new file mode 100644 index 000000000..c508fbd70 --- /dev/null +++ b/src/views/Components/Editor/JsonEditor.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/views/Components/Form/DefaultForm.vue b/src/views/Components/Form/DefaultForm.vue new file mode 100644 index 000000000..4165c1619 --- /dev/null +++ b/src/views/Components/Form/DefaultForm.vue @@ -0,0 +1,1863 @@ + + + + + diff --git a/src/views/Components/Form/UseFormDemo.vue b/src/views/Components/Form/UseFormDemo.vue new file mode 100644 index 000000000..de9cc64d1 --- /dev/null +++ b/src/views/Components/Form/UseFormDemo.vue @@ -0,0 +1,470 @@ + + + + + diff --git a/src/views/Components/Highlight.vue b/src/views/Components/Highlight.vue new file mode 100644 index 000000000..96baedc66 --- /dev/null +++ b/src/views/Components/Highlight.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Components/IAgree.vue b/src/views/Components/IAgree.vue new file mode 100644 index 000000000..947226bc9 --- /dev/null +++ b/src/views/Components/IAgree.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/views/Components/Icon.vue b/src/views/Components/Icon.vue new file mode 100644 index 000000000..02da12a44 --- /dev/null +++ b/src/views/Components/Icon.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/views/Components/IconPicker.vue b/src/views/Components/IconPicker.vue new file mode 100644 index 000000000..6643f949a --- /dev/null +++ b/src/views/Components/IconPicker.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/views/Components/ImageCropping.vue b/src/views/Components/ImageCropping.vue new file mode 100644 index 000000000..9e6995203 --- /dev/null +++ b/src/views/Components/ImageCropping.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/Components/ImageViewer.vue b/src/views/Components/ImageViewer.vue new file mode 100644 index 000000000..a20ce91de --- /dev/null +++ b/src/views/Components/ImageViewer.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/views/Components/Infotip.vue b/src/views/Components/Infotip.vue new file mode 100644 index 000000000..49cff12db --- /dev/null +++ b/src/views/Components/Infotip.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/views/Components/InputPassword.vue b/src/views/Components/InputPassword.vue new file mode 100644 index 000000000..bfae7e523 --- /dev/null +++ b/src/views/Components/InputPassword.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/views/Components/Qrcode.vue b/src/views/Components/Qrcode.vue new file mode 100644 index 000000000..6b7d792fd --- /dev/null +++ b/src/views/Components/Qrcode.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/views/Components/Search.vue b/src/views/Components/Search.vue new file mode 100644 index 000000000..0cc915418 --- /dev/null +++ b/src/views/Components/Search.vue @@ -0,0 +1,363 @@ + + + + + diff --git a/src/views/Components/Table/CardTable.vue b/src/views/Components/Table/CardTable.vue new file mode 100644 index 000000000..f07059d07 --- /dev/null +++ b/src/views/Components/Table/CardTable.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/views/Components/Table/DefaultTable.vue b/src/views/Components/Table/DefaultTable.vue new file mode 100644 index 000000000..1d9124a88 --- /dev/null +++ b/src/views/Components/Table/DefaultTable.vue @@ -0,0 +1,105 @@ + + + diff --git a/src/views/Components/Table/TableImagePreview.vue b/src/views/Components/Table/TableImagePreview.vue new file mode 100644 index 000000000..ded2d6d81 --- /dev/null +++ b/src/views/Components/Table/TableImagePreview.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/views/Components/Table/TableVideoPreview.vue b/src/views/Components/Table/TableVideoPreview.vue new file mode 100644 index 000000000..a6607b08c --- /dev/null +++ b/src/views/Components/Table/TableVideoPreview.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/views/Components/Table/TreeTable.vue b/src/views/Components/Table/TreeTable.vue new file mode 100644 index 000000000..90a1dfb23 --- /dev/null +++ b/src/views/Components/Table/TreeTable.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/src/views/Components/Table/UseTableDemo.vue b/src/views/Components/Table/UseTableDemo.vue new file mode 100644 index 000000000..62e9801ce --- /dev/null +++ b/src/views/Components/Table/UseTableDemo.vue @@ -0,0 +1,283 @@ + + + + + diff --git a/src/views/Components/VideoPlayer.vue b/src/views/Components/VideoPlayer.vue new file mode 100644 index 000000000..66dcad45e --- /dev/null +++ b/src/views/Components/VideoPlayer.vue @@ -0,0 +1,24 @@ + + + diff --git a/src/views/Components/Waterfall.vue b/src/views/Components/Waterfall.vue new file mode 100644 index 000000000..c56f8f85b --- /dev/null +++ b/src/views/Components/Waterfall.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/views/Dashboard/Analysis.vue b/src/views/Dashboard/Analysis.vue new file mode 100644 index 000000000..4ce6f27fb --- /dev/null +++ b/src/views/Dashboard/Analysis.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/views/Dashboard/Workplace.vue b/src/views/Dashboard/Workplace.vue new file mode 100644 index 000000000..4e0bd80e0 --- /dev/null +++ b/src/views/Dashboard/Workplace.vue @@ -0,0 +1,293 @@ + + + diff --git a/src/views/Dashboard/components/PanelGroup.vue b/src/views/Dashboard/components/PanelGroup.vue new file mode 100644 index 000000000..228cf4d6d --- /dev/null +++ b/src/views/Dashboard/components/PanelGroup.vue @@ -0,0 +1,200 @@ + + + + + diff --git a/src/views/Dashboard/echarts-data.ts b/src/views/Dashboard/echarts-data.ts new file mode 100644 index 000000000..00a195eb8 --- /dev/null +++ b/src/views/Dashboard/echarts-data.ts @@ -0,0 +1,309 @@ +import { EChartsOption } from 'echarts' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +export const lineOptions: EChartsOption = { + title: { + text: t('analysis.monthlySales'), + left: 'center' + }, + xAxis: { + data: [ + t('analysis.january'), + t('analysis.february'), + t('analysis.march'), + t('analysis.april'), + t('analysis.may'), + t('analysis.june'), + t('analysis.july'), + t('analysis.august'), + t('analysis.september'), + t('analysis.october'), + t('analysis.november'), + t('analysis.december') + ], + boundaryGap: false, + axisTick: { + show: false + } + }, + grid: { + left: 20, + right: 20, + bottom: 20, + top: 80, + containLabel: true + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross' + }, + padding: [5, 10] + }, + yAxis: { + axisTick: { + show: false + } + }, + legend: { + data: [t('analysis.estimate'), t('analysis.actual')], + top: 50 + }, + series: [ + { + name: t('analysis.estimate'), + smooth: true, + type: 'line', + data: [100, 120, 161, 134, 105, 160, 165, 114, 163, 185, 118, 123], + animationDuration: 2800, + animationEasing: 'cubicInOut' + }, + { + name: t('analysis.actual'), + smooth: true, + type: 'line', + itemStyle: {}, + data: [120, 82, 91, 154, 162, 140, 145, 250, 134, 56, 99, 123], + animationDuration: 2800, + animationEasing: 'quadraticOut' + } + ] +} + +export const pieOptions: EChartsOption = { + title: { + text: t('analysis.userAccessSource'), + left: 'center' + }, + tooltip: { + trigger: 'item', + formatter: '{a}
{b} : {c} ({d}%)' + }, + legend: { + orient: 'vertical', + left: 'left', + data: [ + t('analysis.directAccess'), + t('analysis.mailMarketing'), + t('analysis.allianceAdvertising'), + t('analysis.videoAdvertising'), + t('analysis.searchEngines') + ] + }, + series: [ + { + name: t('analysis.userAccessSource'), + type: 'pie', + radius: '55%', + center: ['50%', '60%'], + data: [ + { value: 335, name: t('analysis.directAccess') }, + { value: 310, name: t('analysis.mailMarketing') }, + { value: 234, name: t('analysis.allianceAdvertising') }, + { value: 135, name: t('analysis.videoAdvertising') }, + { value: 1548, name: t('analysis.searchEngines') } + ] + } + ] +} + +export const barOptions: EChartsOption = { + title: { + text: t('analysis.weeklyUserActivity'), + left: 'center' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + left: 50, + right: 20, + bottom: 20 + }, + xAxis: { + type: 'category', + data: [ + t('analysis.monday'), + t('analysis.tuesday'), + t('analysis.wednesday'), + t('analysis.thursday'), + t('analysis.friday'), + t('analysis.saturday'), + t('analysis.sunday') + ], + axisTick: { + alignWithLabel: true + } + }, + yAxis: { + type: 'value' + }, + series: [ + { + name: t('analysis.activeQuantity'), + data: [13253, 34235, 26321, 12340, 24643, 1322, 1324], + type: 'bar' + } + ] +} + +export const radarOption: EChartsOption = { + legend: { + data: [t('workplace.personal'), t('workplace.team')] + }, + radar: { + // shape: 'circle', + indicator: [ + { name: t('workplace.quote'), max: 65 }, + { name: t('workplace.contribution'), max: 160 }, + { name: t('workplace.hot'), max: 300 }, + { name: t('workplace.yield'), max: 130 }, + { name: t('workplace.follow'), max: 100 } + ] + }, + series: [ + { + name: `xxx${t('workplace.index')}`, + type: 'radar', + data: [ + { + value: [42, 30, 20, 35, 80], + name: t('workplace.personal') + }, + { + value: [50, 140, 290, 100, 90], + name: t('workplace.team') + } + ] + } + ] +} + +export const wordOptions = { + series: [ + { + type: 'wordCloud', + gridSize: 2, + sizeRange: [12, 50], + rotationRange: [-90, 90], + shape: 'pentagon', + width: 600, + height: 400, + drawOutOfBound: true, + textStyle: { + color: function () { + return ( + 'rgb(' + + [ + Math.round(Math.random() * 160), + Math.round(Math.random() * 160), + Math.round(Math.random() * 160) + ].join(',') + + ')' + ) + } + }, + emphasis: { + textStyle: { + shadowBlur: 10, + shadowColor: '#333' + } + }, + data: [ + { + name: 'Sam S Club', + value: 10000, + textStyle: { + color: 'black' + }, + emphasis: { + textStyle: { + color: 'red' + } + } + }, + { + name: 'Macys', + value: 6181 + }, + { + name: 'Amy Schumer', + value: 4386 + }, + { + name: 'Jurassic World', + value: 4055 + }, + { + name: 'Charter Communications', + value: 2467 + }, + { + name: 'Chick Fil A', + value: 2244 + }, + { + name: 'Planet Fitness', + value: 1898 + }, + { + name: 'Pitch Perfect', + value: 1484 + }, + { + name: 'Express', + value: 1112 + }, + { + name: 'Home', + value: 965 + }, + { + name: 'Johnny Depp', + value: 847 + }, + { + name: 'Lena Dunham', + value: 582 + }, + { + name: 'Lewis Hamilton', + value: 555 + }, + { + name: 'KXAN', + value: 550 + }, + { + name: 'Mary Ellen Mark', + value: 462 + }, + { + name: 'Farrah Abraham', + value: 366 + }, + { + name: 'Rita Ora', + value: 360 + }, + { + name: 'Serena Williams', + value: 282 + }, + { + name: 'NCAA baseball tournament', + value: 273 + }, + { + name: 'Point Break', + value: 265 + } + ] + } + ] +} diff --git a/src/views/Error/403.vue b/src/views/Error/403.vue new file mode 100644 index 000000000..615c940b3 --- /dev/null +++ b/src/views/Error/403.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/Error/404.vue b/src/views/Error/404.vue new file mode 100644 index 000000000..0a3fbbe92 --- /dev/null +++ b/src/views/Error/404.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/Error/500.vue b/src/views/Error/500.vue new file mode 100644 index 000000000..ddb50978c --- /dev/null +++ b/src/views/Error/500.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/Example/Dialog/ExampleDialog.vue b/src/views/Example/Dialog/ExampleDialog.vue new file mode 100644 index 000000000..b93450da4 --- /dev/null +++ b/src/views/Example/Dialog/ExampleDialog.vue @@ -0,0 +1,340 @@ + + + diff --git a/src/views/Example/Dialog/components/Detail.vue b/src/views/Example/Dialog/components/Detail.vue new file mode 100644 index 000000000..2496e75a0 --- /dev/null +++ b/src/views/Example/Dialog/components/Detail.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Example/Dialog/components/Write.vue b/src/views/Example/Dialog/components/Write.vue new file mode 100644 index 000000000..2ea183a8c --- /dev/null +++ b/src/views/Example/Dialog/components/Write.vue @@ -0,0 +1,63 @@ + + + diff --git a/src/views/Example/Page/ExampleAdd.vue b/src/views/Example/Page/ExampleAdd.vue new file mode 100644 index 000000000..fbe7460d6 --- /dev/null +++ b/src/views/Example/Page/ExampleAdd.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/views/Example/Page/ExampleDetail.vue b/src/views/Example/Page/ExampleDetail.vue new file mode 100644 index 000000000..6f7e44cb8 --- /dev/null +++ b/src/views/Example/Page/ExampleDetail.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/views/Example/Page/ExampleEdit.vue b/src/views/Example/Page/ExampleEdit.vue new file mode 100644 index 000000000..eb6572120 --- /dev/null +++ b/src/views/Example/Page/ExampleEdit.vue @@ -0,0 +1,66 @@ + + + +@/hooks/event/useEventBus diff --git a/src/views/Example/Page/ExamplePage.vue b/src/views/Example/Page/ExamplePage.vue new file mode 100644 index 000000000..c13fe3cd4 --- /dev/null +++ b/src/views/Example/Page/ExamplePage.vue @@ -0,0 +1,297 @@ + + + +@/hooks/event/useEventBus diff --git a/src/views/Example/Page/components/Detail.vue b/src/views/Example/Page/components/Detail.vue new file mode 100644 index 000000000..11d4a9464 --- /dev/null +++ b/src/views/Example/Page/components/Detail.vue @@ -0,0 +1,69 @@ + + + diff --git a/src/views/Example/Page/components/Write.vue b/src/views/Example/Page/components/Write.vue new file mode 100644 index 000000000..c4f50ad81 --- /dev/null +++ b/src/views/Example/Page/components/Write.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/views/Function/MultipleTabs.vue b/src/views/Function/MultipleTabs.vue new file mode 100644 index 000000000..4a623c8fd --- /dev/null +++ b/src/views/Function/MultipleTabs.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/views/Function/MultipleTabsDemo.vue b/src/views/Function/MultipleTabsDemo.vue new file mode 100644 index 000000000..9421a9aa5 --- /dev/null +++ b/src/views/Function/MultipleTabsDemo.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/views/Function/Request.vue b/src/views/Function/Request.vue new file mode 100644 index 000000000..b37e67bb1 --- /dev/null +++ b/src/views/Function/Request.vue @@ -0,0 +1,173 @@ + + + diff --git a/src/views/Function/Test.vue b/src/views/Function/Test.vue new file mode 100644 index 000000000..dbb37325e --- /dev/null +++ b/src/views/Function/Test.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/views/Guide/Guide.vue b/src/views/Guide/Guide.vue new file mode 100644 index 000000000..dbdc91b31 --- /dev/null +++ b/src/views/Guide/Guide.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/views/Level/Menu111.vue b/src/views/Level/Menu111.vue new file mode 100644 index 000000000..015d0f894 --- /dev/null +++ b/src/views/Level/Menu111.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Level/Menu12.vue b/src/views/Level/Menu12.vue new file mode 100644 index 000000000..8e2725dbc --- /dev/null +++ b/src/views/Level/Menu12.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Level/Menu2.vue b/src/views/Level/Menu2.vue new file mode 100644 index 000000000..72e2abb95 --- /dev/null +++ b/src/views/Level/Menu2.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue new file mode 100644 index 000000000..132d1541d --- /dev/null +++ b/src/views/Login/Login.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue new file mode 100644 index 000000000..ddb55c9a1 --- /dev/null +++ b/src/views/Login/components/LoginForm.vue @@ -0,0 +1,580 @@ + + + + + diff --git a/src/views/Login/components/RegisterForm.vue b/src/views/Login/components/RegisterForm.vue new file mode 100644 index 000000000..1f3d25183 --- /dev/null +++ b/src/views/Login/components/RegisterForm.vue @@ -0,0 +1,218 @@ + + + diff --git a/src/views/Login/components/index.ts b/src/views/Login/components/index.ts new file mode 100644 index 000000000..d08be9667 --- /dev/null +++ b/src/views/Login/components/index.ts @@ -0,0 +1,4 @@ +import LoginForm from './LoginForm.vue' +import RegisterForm from './RegisterForm.vue' + +export { LoginForm, RegisterForm } diff --git a/src/views/Personal/PersonalCenter/PersonalCenter.vue b/src/views/Personal/PersonalCenter/PersonalCenter.vue new file mode 100644 index 000000000..dc0988378 --- /dev/null +++ b/src/views/Personal/PersonalCenter/PersonalCenter.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/views/Personal/PersonalCenter/components/EditInfo.vue b/src/views/Personal/PersonalCenter/components/EditInfo.vue new file mode 100644 index 000000000..bd684b74a --- /dev/null +++ b/src/views/Personal/PersonalCenter/components/EditInfo.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/Personal/PersonalCenter/components/EditPassword.vue b/src/views/Personal/PersonalCenter/components/EditPassword.vue new file mode 100644 index 000000000..7b320f3a8 --- /dev/null +++ b/src/views/Personal/PersonalCenter/components/EditPassword.vue @@ -0,0 +1,110 @@ + + + diff --git a/src/views/Personal/PersonalCenter/components/UploadAvatar.vue b/src/views/Personal/PersonalCenter/components/UploadAvatar.vue new file mode 100644 index 000000000..9b40e218c --- /dev/null +++ b/src/views/Personal/PersonalCenter/components/UploadAvatar.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/views/Redirect/Redirect.vue b/src/views/Redirect/Redirect.vue new file mode 100644 index 000000000..0b7af7b23 --- /dev/null +++ b/src/views/Redirect/Redirect.vue @@ -0,0 +1,30 @@ + + diff --git a/src/views/hooks/useClipboard.vue b/src/views/hooks/useClipboard.vue new file mode 100644 index 000000000..f49125ec3 --- /dev/null +++ b/src/views/hooks/useClipboard.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/views/hooks/useCrudSchemas.vue b/src/views/hooks/useCrudSchemas.vue new file mode 100644 index 000000000..69a2d7f62 --- /dev/null +++ b/src/views/hooks/useCrudSchemas.vue @@ -0,0 +1,186 @@ + + + diff --git a/src/views/hooks/useNetwork.vue b/src/views/hooks/useNetwork.vue new file mode 100644 index 000000000..dd6ed934e --- /dev/null +++ b/src/views/hooks/useNetwork.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/views/hooks/useTagsView.vue b/src/views/hooks/useTagsView.vue new file mode 100644 index 000000000..1bacedcf7 --- /dev/null +++ b/src/views/hooks/useTagsView.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/views/hooks/useValidator.vue b/src/views/hooks/useValidator.vue new file mode 100644 index 000000000..c3d6131fe --- /dev/null +++ b/src/views/hooks/useValidator.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/views/hooks/useWatermark.vue b/src/views/hooks/useWatermark.vue new file mode 100644 index 000000000..bd5cc84ed --- /dev/null +++ b/src/views/hooks/useWatermark.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/vtj.ts b/src/vtj.ts new file mode 100644 index 000000000..e5ef6954a --- /dev/null +++ b/src/vtj.ts @@ -0,0 +1,175 @@ +import type { App } from 'vue' +import type { Router } from 'vue-router' +import { + createProvider, + LocalService, + createModules, + NodeEnv, + autoUpdate, + ContextMode, + notify, + loading, + createAdapter, + createServiceRequest, + kebabCase +} from '@vtj/web' +import type { ProjectSchema, PageFile } from '@vtj/core' +import '@vtj/web/src/index.scss' + +export interface SetupVtjOptions { + id: string + app: App + ready?: () => void +} + +export interface setupVtjRoutesOptions { + id: string + router: Router + routes: any[] + layout: any +} + +export function setupVtj(options: SetupVtjOptions) { + const { id, app, ready } = options + const adapter = createAdapter({ loading, notify }) + const service = new LocalService(createServiceRequest(notify)) + const modules = createModules() + const { provider, onReady } = createProvider({ + nodeEnv: process.env.NODE_ENV as NodeEnv, + mode: ContextMode.Raw, + modules, + adapter, + service, + dependencies: { + Vue: () => import('vue'), + VueRouter: () => import('vue-router') + }, + project: { + id + } + }) + + onReady(async () => { + app.use(provider) + ready && ready() + }) + + if (process.env.NODE_ENV === 'production') { + autoUpdate() + } +} + +function toElIcon(icon?: string) { + return icon ? `vi-ep:${kebabCase(icon)}` : undefined +} + +function createPageRoute(page: PageFile) { + const { id, title, icon, hidden, cache = false, meta = {} } = page + return { + path: `page/${id}`, + name: `Page_${id}`, + component: () => import(`$vtj/vue/${id}.vue`), + meta: { + title, + hidden, + icon: toElIcon(icon), + noCache: !cache, + ...meta + } + } +} + +function createNoMaskRoute(page: PageFile) { + const { id, title, icon, cache = false, meta = {} } = page + return { + path: `/page/${id}`, + component: () => import(`$vtj/vue/${id}.vue`), + meta: { + title, + icon: toElIcon(icon), + hidden: true, + noCache: !cache, + ...meta + } + } +} + +function childrenToRoutes(children: PageFile[] = [], noMask: any[]) { + return children.map((child) => { + const { id, dir, mask = true, title, icon, hidden } = child + if (dir) { + return { + path: '', + name: `Dir_${id}`, + redirect: `/page/${id}`, + meta: { + hidden, + title, + alwaysShow: true, + icon: toElIcon(icon) + }, + children: childrenToRoutes(child.children, noMask) + } + } + if (!mask) { + noMask.push(createNoMaskRoute(child)) + } + return createPageRoute(child) + }) +} + +function pagesToRoutes(pages: PageFile[], layout: any) { + const noMask: any[] = [] + const items: any[] = [] + for (const page of pages) { + const { id, dir, mask = true, title, icon, hidden, children = [] } = page + if (!dir && !mask) { + noMask.push(createNoMaskRoute(page)) + } + + if (children.length) { + items.push({ + path: '/', + name: `Root_${id}`, + component: layout, + meta: { + hidden, + title, + alwaysShow: true, + icon: toElIcon(icon) + }, + children: childrenToRoutes(children, noMask) + }) + } else { + items.push({ + path: '/', + name: `Root_${id}`, + component: layout, + meta: { + hidden, + title, + alwaysShow: !!dir, + icon: toElIcon(icon) + }, + children: dir ? [] : [createPageRoute(page)] + }) + } + } + return [...noMask, ...items] +} + +export async function setupVtjRoutes(options: setupVtjRoutesOptions) { + const modules = createModules() + const { id, layout, routes, router } = options + const loader = modules[`.vtj/projects/${id}.json`] + if (loader) { + const project = ((await loader()) as any).default as ProjectSchema + const pages = project.pages || [] + const pageRoutes = pagesToRoutes(pages, layout) + console.log(pageRoutes) + routes.unshift(...pageRoutes) + routes.forEach((item) => { + router.addRoute(item) + }) + } +} diff --git a/stylelint.config.cjs b/stylelint.config.cjs new file mode 100644 index 000000000..a50d2028a --- /dev/null +++ b/stylelint.config.cjs @@ -0,0 +1,231 @@ +module.exports = { + root: true, + plugins: ['stylelint-order'], + customSyntax: 'postcss-html', + extends: ['stylelint-config-standard'], + rules: { + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global', 'deep'] + } + ], + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: ['function', 'if', 'each', 'include', 'mixin'] + } + ], + 'media-query-no-invalid': null, + 'function-no-unknown': null, + 'no-empty-source': null, + 'named-grid-areas-no-invalid': null, + 'no-descending-specificity': null, + 'font-family-no-missing-generic-family-keyword': null, + 'rule-empty-line-before': [ + 'always', + { + ignore: ['after-comment', 'first-nested'] + } + ], + 'unit-no-unknown': [ + true, + { + ignoreUnits: ['rpx'] + } + ], + 'order/order': [ + [ + 'dollar-variables', + 'custom-properties', + 'at-rules', + 'declarations', + { + type: 'at-rule', + name: 'supports' + }, + { + type: 'at-rule', + name: 'media' + }, + 'rules' + ], + { + severity: 'warning' + } + ], + // Specify the alphabetical order of the attributes in the declaration block + 'order/properties-order': [ + 'position', + 'top', + 'right', + 'bottom', + 'left', + 'z-index', + 'display', + 'float', + 'width', + 'height', + 'max-width', + 'max-height', + 'min-width', + 'min-height', + 'padding', + 'padding-top', + 'padding-right', + 'padding-bottom', + 'padding-left', + 'margin', + 'margin-top', + 'margin-right', + 'margin-bottom', + 'margin-left', + 'margin-collapse', + 'margin-top-collapse', + 'margin-right-collapse', + 'margin-bottom-collapse', + 'margin-left-collapse', + 'overflow', + 'overflow-x', + 'overflow-y', + 'clip', + 'clear', + 'font', + 'font-family', + 'font-size', + 'font-smoothing', + 'osx-font-smoothing', + 'font-style', + 'font-weight', + 'hyphens', + 'src', + 'line-height', + 'letter-spacing', + 'word-spacing', + 'color', + 'text-align', + 'text-decoration', + 'text-indent', + 'text-overflow', + 'text-rendering', + 'text-size-adjust', + 'text-shadow', + 'text-transform', + 'word-break', + 'word-wrap', + 'white-space', + 'vertical-align', + 'list-style', + 'list-style-type', + 'list-style-position', + 'list-style-image', + 'pointer-events', + 'cursor', + 'background', + 'background-attachment', + 'background-color', + 'background-image', + 'background-position', + 'background-repeat', + 'background-size', + 'border', + 'border-collapse', + 'border-top', + 'border-right', + 'border-bottom', + 'border-left', + 'border-color', + 'border-image', + 'border-top-color', + 'border-right-color', + 'border-bottom-color', + 'border-left-color', + 'border-spacing', + 'border-style', + 'border-top-style', + 'border-right-style', + 'border-bottom-style', + 'border-left-style', + 'border-width', + 'border-top-width', + 'border-right-width', + 'border-bottom-width', + 'border-left-width', + 'border-radius', + 'border-top-right-radius', + 'border-bottom-right-radius', + 'border-bottom-left-radius', + 'border-top-left-radius', + 'border-radius-topright', + 'border-radius-bottomright', + 'border-radius-bottomleft', + 'border-radius-topleft', + 'content', + 'quotes', + 'outline', + 'outline-offset', + 'opacity', + 'filter', + 'visibility', + 'size', + 'zoom', + 'transform', + 'box-align', + 'box-flex', + 'box-orient', + 'box-pack', + 'box-shadow', + 'box-sizing', + 'table-layout', + 'animation', + 'animation-delay', + 'animation-duration', + 'animation-iteration-count', + 'animation-name', + 'animation-play-state', + 'animation-timing-function', + 'animation-fill-mode', + 'transition', + 'transition-delay', + 'transition-duration', + 'transition-property', + 'transition-timing-function', + 'background-clip', + 'backface-visibility', + 'resize', + 'appearance', + 'user-select', + 'interpolation-mode', + 'direction', + 'marks', + 'page', + 'set-link-source', + 'unicode-bidi', + 'speak' + ] + }, + ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'], + overrides: [ + { + files: ['*.vue', '**/*.vue', '*.html', '**/*.html'], + extends: ['stylelint-config-recommended', 'stylelint-config-html'], + rules: { + 'keyframes-name-pattern': null, + 'selector-class-pattern': null, + 'no-duplicate-selectors': null, + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['deep', 'global'] + } + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'] + } + ] + } + } + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..908517f4a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "jsxImportSource": "vue", + "lib": ["esnext", "dom"], + "baseUrl": "./", + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true, + "strictFunctionTypes": false, + "noUnusedLocals": true, + "noUnusedParameters": true, + "experimentalDecorators": true, + "noImplicitAny": false, + "skipLibCheck": true, + "paths": { + "@/*": ["src/*"] + }, + "types": [ + "@intlify/unplugin-vue-i18n/types", + "vite/client", + "element-plus/global", + "@types/qrcode", + "vite-plugin-svg-icons/client" + ] + }, + "include": ["src", "types/**/*.d.ts", "mock/**/*.ts"], + "exclude": ["dist", "node_modules", ".vtj"] +} diff --git a/types/components.d.ts b/types/components.d.ts new file mode 100644 index 000000000..15b5a6bdf --- /dev/null +++ b/types/components.d.ts @@ -0,0 +1,9 @@ +declare module 'vue' { + export interface GlobalComponents { + Icon: (typeof import('../src/components/Icon/index'))['Icon'] + Permission: (typeof import('../src/components/Permission/index'))['Permission'] + BaseButton: (typeof import('../src/components/Button/index'))['BaseButton'] + } +} + +export {} diff --git a/types/env.d.ts b/types/env.d.ts new file mode 100644 index 000000000..38117253d --- /dev/null +++ b/types/env.d.ts @@ -0,0 +1,14 @@ +/// + +declare module '*.vue' { + import { DefineComponent } from 'vue' + + const component: DefineComponent<{}, {}, any> + export default component +} + +declare global { + interface ImportMeta { + readonly env: ImportMetaEnv + } +} diff --git a/types/global.d.ts b/types/global.d.ts new file mode 100644 index 000000000..c8ef5eda5 --- /dev/null +++ b/types/global.d.ts @@ -0,0 +1,87 @@ +import type { CSSProperties } from 'vue' +import { RawAxiosRequestHeaders } from 'axios' +declare global { + declare interface Fn { + (...arg: T[]): T + } + + declare type Nullable = T | null + + declare type ElRef = Nullable + + declare type Recordable = Record + + declare type RemoveReadonly = { + -readonly [P in keyof T]: T[P] + } + + declare type ComponentRef = InstanceType + + declare type LocaleType = 'zh-CN' | 'en' + + declare type TimeoutHandle = ReturnType + declare type IntervalHandle = ReturnType + + declare type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger' + + declare type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu' + + declare type AxiosContentType = + | 'application/json' + | 'application/x-www-form-urlencoded' + | 'multipart/form-data' + | 'text/plain' + + declare type AxiosMethod = 'get' | 'post' | 'delete' | 'put' + + declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' + + declare interface AxiosConfig { + params?: any + data?: any + url?: string + method?: AxiosMethod + headers?: RawAxiosRequestHeaders + responseType?: AxiosResponseType + } + + declare interface IResponse { + code: number + data: T extends any ? T : T & any + } + + declare interface ThemeTypes { + elColorPrimary?: string + leftMenuBorderColor?: string + leftMenuBgColor?: string + leftMenuBgLightColor?: string + leftMenuBgActiveColor?: string + leftMenuCollapseBgActiveColor?: string + leftMenuTextColor?: string + leftMenuTextActiveColor?: string + logoTitleTextColor?: string + logoBorderColor?: string + topHeaderBgColor?: string + topHeaderTextColor?: string + topHeaderHoverColor?: string + topToolBorderColor?: string + } + + declare interface ImportMetaEnv { + readonly VITE_NODE_ENV: string + readonly VITE_APP_TITLE: string + readonly VITE_API_BASE_PATH: string + readonly VITE_BASE_PATH: string + readonly VITE_DROP_DEBUGGER: string + readonly VITE_DROP_CONSOLE: string + readonly VITE_SOURCEMAP: string + readonly VITE_OUT_DIR: string + readonly VITE_USE_BUNDLE_ANALYZER: string + readonly VITE_USE_ALL_ELEMENT_PLUS_STYLE: string + readonly VITE_USE_MOCK: string + readonly VITE_USE_CSS_SPLIT: string + readonly VITE_USE_ONLINE_ICON: string + readonly VITE_ICON_PREFIX: string + readonly VITE_HIDE_GLOBAL_SETTING: string + } +} diff --git a/types/router.d.ts b/types/router.d.ts new file mode 100644 index 000000000..32d944705 --- /dev/null +++ b/types/router.d.ts @@ -0,0 +1,78 @@ +import type { RouteRecordRaw } from 'vue-router' +import { defineComponent } from 'vue' + +/** +* redirect: noredirect 当设置 noredirect 的时候该路由在面包屑导航中不可被点击 +* name:'router-name' 设定路由的名字,一定要填写不然使用时会出现各种问题 +* meta : { + hidden: true 当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false) + + alwaysShow: true 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式, + 只有一个时,会将那个子路由当做根路由显示在侧边栏, + 若你想不管路由下面的 children 声明的个数都显示你的根路由, + 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则, + 一直显示根路由(默认 false) + + title: 'title' 设置该路由在侧边栏和面包屑中展示的名字 + + icon: 'svg-name' 设置该路由的图标 + + noCache: true 如果设置为true,则不会被 缓存(默认 false) + + breadcrumb: false 如果设置为false,则不会在breadcrumb面包屑中显示(默认 true) + + affix: true 如果设置为true,则会一直固定在tag项中(默认 false) + + noTagsView: true 如果设置为true,则不会出现在tag中(默认 false) + + activeMenu: '/dashboard' 显示高亮的路由路径 + + canTo: true 设置为true即使hidden为true,也依然可以进行路由跳转(默认 false) + + permission: ['edit','add', 'delete'] 设置该路由的权限 + } +**/ + +interface RouteMetaCustom extends Record { + hidden?: boolean + alwaysShow?: boolean + title?: string + icon?: string + noCache?: boolean + breadcrumb?: boolean + affix?: boolean + activeMenu?: string + noTagsView?: boolean + canTo?: boolean + permission?: string[] +} + +declare module 'vue-router' { + interface RouteMeta extends RouteMetaCustom {} +} + +type Component = + | ReturnType + | (() => Promise) + | (() => Promise) + +declare global { + declare interface AppRouteRecordRaw extends Omit { + name: string + meta: RouteMetaCustom + component?: Component | string + children?: AppRouteRecordRaw[] + props?: Recordable + fullPath?: string + } + + declare interface AppCustomRouteRecordRaw + extends Omit { + name: string + meta: RouteMetaCustom + component: string + path: string + redirect: string + children?: AppCustomRouteRecordRaw[] + } +} diff --git a/uno.config.ts b/uno.config.ts new file mode 100644 index 000000000..997f6c895 --- /dev/null +++ b/uno.config.ts @@ -0,0 +1,146 @@ +import { defineConfig, toEscapedSelector as e, presetUno, presetIcons } from 'unocss' +import transformerVariantGroup from '@unocss/transformer-variant-group' +import { loadEnv } from 'vite' +import { ICON_PREFIX } from './src/constants' + +const root = process.cwd() + +const createPresetIcons = () => { + const isBuild = !!process.argv[4] + let env = {} as any + if (!isBuild) { + env = loadEnv(process.argv[3], root) + } else { + env = loadEnv(process.argv[4], root) + } + // @ts-ignore + if (env.VITE_USE_ONLINE_ICON === 'true') { + return [] + } else { + return [ + presetIcons({ + autoInstall: false, + prefix: ICON_PREFIX + }) + ] + } +} + +export default defineConfig({ + // ...UnoCSS options + rules: [ + [ + /^overflow-ellipsis$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector} { + text-overflow: ellipsis; +} +` + } + ], + [ + /^custom-hover$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector} { + display: flex; + height: 100%; + padding: 1px 10px 0; + cursor: pointer; + align-items: center; + transition: background var(--transition-time-02); +} +/* you can have multiple rules */ +${selector}:hover { + background-color: var(--top-header-hover-color); +} +.dark ${selector}:hover { + background-color: var(--el-bg-color-overlay); +} +` + } + ], + [ + /^layout-border__left$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector}:before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 1px; + height: 100%; + background-color: var(--el-border-color); + z-index: 3; +} +` + } + ], + [ + /^layout-border__right$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector}:after { + content: ""; + position: absolute; + top: 0; + right: 0; + width: 1px; + height: 100%; + background-color: var(--el-border-color); + z-index: 3; +} +` + } + ], + [ + /^layout-border__top$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector}:before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1px; + background-color: var(--el-border-color); + z-index: 3; +} +` + } + ], + [ + /^layout-border__bottom$/, + ([], { rawSelector }) => { + const selector = e(rawSelector) + return ` +${selector}:after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + background-color: var(--el-border-color); + z-index: 3; +} +` + } + ] + ], + presets: [presetUno({ dark: 'class', attributify: false }), ...createPresetIcons()], + transformers: [transformerVariantGroup()], + content: { + pipeline: { + include: [/\.(vue|svelte|[jt]sx|mdx?|astro|elm|php|phtml|html|ts)($|\?)/] + } + } +}) diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 000000000..2654107c4 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,205 @@ +import { resolve } from 'path' +import { loadEnv } from 'vite' +import type { UserConfig, ConfigEnv } from 'vite' +import Vue from '@vitejs/plugin-vue' +import VueJsx from '@vitejs/plugin-vue-jsx' +import progress from 'vite-plugin-progress' +import EslintPlugin from 'vite-plugin-eslint' +import { ViteEjsPlugin } from 'vite-plugin-ejs' +import { viteMockServe } from 'vite-plugin-mock' +import PurgeIcons from 'vite-plugin-purge-icons' +import ServerUrlCopy from 'vite-plugin-url-copy' +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import' +import UnoCSS from 'unocss/vite' +import { visualizer } from 'rollup-plugin-visualizer' +import { createDevTools } from '@vtj/pro/vite' + +// https://vitejs.dev/config/ +const root = process.cwd() + +function pathResolve(dir: string) { + return resolve(root, '.', dir) +} + +export default ({ command, mode }: ConfigEnv): UserConfig => { + let env = {} as any + const isBuild = command === 'build' + if (!isBuild) { + env = loadEnv(process.argv[3] === '--mode' ? process.argv[4] : process.argv[3], root) + } else { + env = loadEnv(mode, root) + } + return { + base: env.VITE_BASE_PATH, + plugins: [ + Vue({ + script: { + // 开启defineModel + defineModel: true + }, + // 禁用开发环境下的严格模式,避免组件重复渲染导致重复请求 + template: { + compilerOptions: { + isCustomElement: (tag) => tag.includes('-') + } + } + }), + VueJsx(), + ServerUrlCopy(), + progress(), + env.VITE_USE_ALL_ELEMENT_PLUS_STYLE === 'false' + ? createStyleImportPlugin({ + resolves: [ElementPlusResolve()], + libs: [ + { + libraryName: 'element-plus', + esModule: true, + resolveStyle: (name) => { + if (name === 'click-outside') { + return '' + } + return `element-plus/es/components/${name.replace(/^el-/, '')}/style/css` + } + } + ] + }) + : undefined, + EslintPlugin({ + cache: false, + failOnWarning: false, + failOnError: false, + include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件 + }), + VueI18nPlugin({ + runtimeOnly: true, + compositionOnly: true, + include: [resolve(__dirname, 'src/locales/**')] + }), + createSvgIconsPlugin({ + iconDirs: [pathResolve('src/assets/svgs')], + symbolId: 'icon-[dir]-[name]', + svgoOptions: true + }), + PurgeIcons(), + env.VITE_USE_MOCK === 'true' + ? viteMockServe({ + ignore: /^\_/, + mockPath: 'mock', + localEnabled: !isBuild, + prodEnabled: isBuild, + injectCode: ` + import { setupProdMockServer } from '../mock/_createProductionServer' + + setupProdMockServer() + ` + }) + : undefined, + ViteEjsPlugin({ + title: env.VITE_APP_TITLE + }), + UnoCSS(), + createDevTools() + ], + + css: { + preprocessorOptions: { + less: { + additionalData: '@import "./src/styles/variables.module.less";', + javascriptEnabled: true + } + } + }, + resolve: { + extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.less', '.css'], + alias: [ + { + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js' + }, + { + find: /\@\//, + replacement: `${pathResolve('src')}/` + } + ] + }, + esbuild: { + pure: env.VITE_DROP_CONSOLE === 'true' ? ['console.log'] : undefined, + drop: env.VITE_DROP_DEBUGGER === 'true' ? ['debugger'] : undefined + }, + build: { + target: 'es2015', + outDir: env.VITE_OUT_DIR || 'dist', + sourcemap: env.VITE_SOURCEMAP === 'true', + // brotliSize: false, + rollupOptions: { + plugins: env.VITE_USE_BUNDLE_ANALYZER === 'true' ? [visualizer()] : undefined, + // 拆包 + output: { + manualChunks: { + 'vue-chunks': ['vue', 'vue-router', 'pinia', 'vue-i18n'], + 'element-plus': ['element-plus'], + 'wang-editor': ['@wangeditor/editor', '@wangeditor/editor-for-vue'], + echarts: ['echarts', 'echarts-wordcloud'] + } + } + }, + cssCodeSplit: !(env.VITE_USE_CSS_SPLIT === 'false'), + cssTarget: ['chrome31'] + }, + // 服务端渲染 + server: { + port: env.VITE_PORT, // 端口号 + host: "0.0.0.0", + open: env.VITE_OPEN === 'true', + // 添加代理配置,解决跨域问题 + proxy: { + '/admin-api': { + target: 'http://39.104.23.25:48080', + ws: false, + changeOrigin: true, + // 确保OPTIONS请求也能正确处理 + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Tenant-Id' + } + }, + // 直接代理验证码接口 + '/system/captcha': { + target: 'http://39.104.23.25:48080/admin-api', + changeOrigin: true, + // 确保OPTIONS请求也能正确处理 + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Tenant-Id' + } + } + }, + }, + optimizeDeps: { + include: [ + 'vue', + 'vue-router', + 'vue-types', + 'element-plus/es/locale/lang/zh-cn', + 'element-plus/es/locale/lang/en', + '@iconify/iconify', + '@vueuse/core', + 'axios', + 'qs', + 'echarts', + 'echarts-wordcloud', + 'qrcode', + '@wangeditor/editor', + '@wangeditor/editor-for-vue', + 'vue-json-pretty', + '@zxcvbn-ts/core', + 'dayjs', + 'cropperjs' + ] + } + } +}